uno*_*ode 5 python python-imaging-library
这里有一堆关于 SO 的问题,它们提供了当前问题的答案,但是输出不是预期的。
目标是合并两个 RGBA 图像。每张图像的 alpha 通道上的信息是不一样的。
当前(简化)代码是:
from PIL import Image
image = '1.png'
watermark = '2.png'
wmark = Image.open(watermark)
img = Image.open(image)
img.paste(wmark, (0, 0), wmark)
img.save("result.png", "PNG")
Run Code Online (Sandbox Code Playgroud)
两张图分别是:
背景

前景

预期输出

实际结果

如果您没有看到差异,这里是最终版本的 alpha 通道(为了更好的可视化而反转)。
预期结果 - alpha 通道

实际结果 - alpha 通道

话虽如此,有什么办法可以做到这一点,还是我做错了什么?
编辑 - 在@zenpoy 评论后澄清:
如果前景图像具有一定的不透明度,我希望在叠加两个图像时考虑到这一点,但我不希望将第二个图像的 alpha 通道添加到第一个图像中。就像在纸图像(背景)前面放一块玻璃(前景图像)一样。
换句话说,如果背景图像是 RGB 而不是 RGBA,则最终图像应该没有 alpha 信息。
从您最初的描述来看,以下想法似乎是等效的。令 X、Y 为两个 RGBA 图像。合并 X 和 Y,考虑 X 中的 RGB 波段和 Y 中的 RGBA 波段,生成图像 Z。将 Z 中的波段 A 设置为 X 中的波段 A。这与您的最终陈述相矛盾,但它似乎给出了预期的结果这种情况下的输出。
所以,这是代码:
image = '1.png'
watermark = '2.png'
wmark = Image.open(watermark)
img = Image.open(image)
ia, wa = None, None
if len(img.getbands()) == 4:
ir, ig, ib, ia = img.split()
img = Image.merge('RGB', (ir, ig, ib))
if len(wmark.getbands()) == 4:
wa = wmark.split()[-1]
img.paste(wmark, (0, 0), wmark)
if ia:
if wa:
# XXX This seems to solve the contradiction, discard if unwanted.
ia = max_alpha(wa, ia)
img.putalpha(ia)
img.save('result.png')
Run Code Online (Sandbox Code Playgroud)
其中函数max_alpha是:
def max_alpha(a, b):
# Assumption: 'a' and 'b' are of same size
im_a = a.load()
im_b = b.load()
width, height = a.size
alpha = Image.new('L', (width, height))
im = alpha.load()
for x in xrange(width):
for y in xrange(height):
im[x, y] = max(im_a[x, y], im_b[x, y])
return alpha
Run Code Online (Sandbox Code Playgroud)
这个新功能似乎考虑到了提到的矛盾。