Преобразование RGBA PNG в RGB с помощью PILPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Преобразование RGBA PNG в RGB с помощью PIL

Сообщение Anonymous »

Я использую PIL для преобразования прозрачного изображения PNG, загруженного с помощью Django, в файл JPG. Вывод выглядит поврежденным.

Исходный файл

Изображение


Код

Image.open(object.logo.path).save('/tmp/output.jpg', 'JPEG')


или

Image.open(object.logo.path).convert('RGB').save('/tmp/output.png')


Результат

В обоих случаях результирующее изображение выглядит следующим образом:
Изображение


Есть ли способ это исправить? Я хотел бы иметь белый фон там, где раньше был прозрачный фон.



Решение

Благодаря отличным ответам я придумал следующую коллекцию функций:

import Image
import numpy as np

def alpha_to_color(image, color=(255, 255, 255)):
"""Set all fully transparent pixels of an RGBA image to the specified color.
This is a very simple solution that might leave over some ugly edges, due
to semi-transparent areas. You should use alpha_composite_with color instead.

Source: http://stackoverflow.com/a/9166671/284318

Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)

"""
x = np.array(image)
r, g, b, a = np.rollaxis(x, axis=-1)
r[a == 0] = color[0]
g[a == 0] = color[1]
b[a == 0] = color[2]
x = np.dstack([r, g, b, a])
return Image.fromarray(x, 'RGBA')

def alpha_composite(front, back):
"""Alpha composite two RGBA images.

Source: http://stackoverflow.com/a/9166671/284318

Keyword Arguments:
front -- PIL RGBA Image object
back -- PIL RGBA Image object

"""
front = np.asarray(front)
back = np.asarray(back)
result = np.empty(front.shape, dtype='float')
alpha = np.index_exp[:, :, 3:]
rgb = np.index_exp[:, :, :3]
falpha = front[alpha] / 255.0
balpha = back[alpha] / 255.0
result[alpha] = falpha + balpha * (1 - falpha)
old_setting = np.seterr(invalid='ignore')
result[rgb] = (front[rgb] * falpha + back[rgb] * balpha * (1 - falpha)) / result[alpha]
np.seterr(**old_setting)
result[alpha] *= 255
np.clip(result, 0, 255)
# astype('uint8') maps np.nan and np.inf to 0
result = result.astype('uint8')
result = Image.fromarray(result, 'RGBA')
return result

def alpha_composite_with_color(image, color=(255, 255, 255)):
"""Alpha composite an RGBA image with a single color image of the
specified color and the same size as the original image.

Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)

"""
back = Image.new('RGBA', size=image.size, color=color + (255,))
return alpha_composite(image, back)

def pure_pil_alpha_to_color_v1(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.

NOTE: This version is much slower than the
alpha_composite_with_color solution. Use it only if
numpy is not available.

Source: http://stackoverflow.com/a/9168169/284318

Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)

"""
def blend_value(back, front, a):
return (front * a + back * (255 - a)) / 255

def blend_rgba(back, front):
result = [blend_value(back, front, front[3]) for i in (0, 1, 2)]
return tuple(result + [255])

im = image.copy() # don't edit the reference directly
p = im.load() # load pixel array
for y in range(im.size[1]):
for x in range(im.size[0]):
p[x, y] = blend_rgba(color + (255,), p[x, y])

return im

def pure_pil_alpha_to_color_v2(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.

Simpler, faster version than the solutions above.

Source: http://stackoverflow.com/a/9459208/284318

Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)

"""
image.load() # needed for split()
background = Image.new('RGB', image.size, color)
background.paste(image, mask=image.split()[3]) # 3 is the alpha channel
return background


Производительность

Простая функция альфа_то_цвет без композиции является самым быстрым решением, но оставляет позади некрасивые границы, потому что он не обрабатывает полупрозрачные области.

И чистый PIL, и решения для компоновки numpy дают отличные результаты, но Alpha_composite_with_color работает намного быстрее (8.93 мс), чем pure_pil_alpha_to_color (79,6 мс). Если в вашей системе доступен numpy, это то, что вам нужно. (Обновление: новая чистая версия PIL — самое быстрое из всех упомянутых решений.)

$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_to_color(i)"
10 loops, best of 3: 4.67 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.alpha_composite_with_color(i)"
10 loops, best of 3: 8.93 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color(i)"
10 loops, best of 3: 79.6 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u'logo.png'); i2 = utils.pure_pil_alpha_to_color_v2(i)"
10 loops, best of 3: 1.1 msec per loop


Подробнее здесь: https://stackoverflow.com/questions/916 ... b-with-pil
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Преобразовать RGBA PNG в RGB с PIL
    Anonymous » » в форуме Python
    0 Ответы
    5 Просмотры
    Последнее сообщение Anonymous
  • Загрузка прозрачного PNG в PIL дает RGB вместо RGBA
    Anonymous » » в форуме Python
    0 Ответы
    5 Просмотры
    Последнее сообщение Anonymous
  • Преобразовать RGBA PNG в RGB с PIL
    Anonymous » » в форуме Python
    0 Ответы
    7 Просмотры
    Последнее сообщение Anonymous
  • Преобразовать RGBA PNG в RGB с PIL
    Anonymous » » в форуме Python
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Преобразовать RGBA PNG в RGB с PIL
    Anonymous » » в форуме Python
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»