gpt4 book ai didi

python - 使用 PIL 将 RGBA PNG 转换为 RGB

转载 作者:IT老高 更新时间:2023-10-28 21:31:56 29 4
gpt4 key购买 nike

我正在使用 PIL 将使用 Django 上传的透明 PNG 图像转换为 JPG 文件。输出看起来坏了。

源文件

transparent source file

代码

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

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

结果

两种方式,生成的图像如下所示:

resulting file

有没有办法解决这个问题?我想在原来透明背景的地方有白色背景。


解决方案

感谢出色的答案,我想出了以下函数集合:

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[i], front[i], 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

性能

简单的非合成 alpha_to_color 函数是最快的解决方案,但会留下难看的边框,因为它不处理半透明区域。

纯 PIL 和 numpy 合成解决方案都给出了很好的结果,但是 alpha_composite_with_colorpure_pil_alpha_to_color (79.6 毫秒) 快得多 (8.93 毫秒)。 如果您的系统上可以使用 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

最佳答案

这是一个更简单的版本 - 不确定它的性能如何。很大程度上基于我在构建对 sorl 缩略图的 RGBA -> JPG + BG 支持时发现的一些 django 片段。

from PIL import Image

png = Image.open(object.logo.path)
png.load() # required for png.split()

background = Image.new("RGB", png.size, (255, 255, 255))
background.paste(png, mask=png.split()[3]) # 3 is the alpha channel

background.save('foo.jpg', 'JPEG', quality=80)

结果@80%

enter image description here

结果@50%
enter image description here

关于python - 使用 PIL 将 RGBA PNG 转换为 RGB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9166400/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com