这里有一堆关于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")
这两张图片是:
背景
前景
预期输出
实际结果
如果你没有看到差异,这里是最终版本的alpha通道(倒置以便更好地显示)。
预期结果 - Alpha通道
实际结果 - Alpha通道
所以说,有没有办法做到这一点,或者我做错了什么?
编辑 - 在@zenpoy评论之后澄清:
如果前景图像具有一定的不透明度,我希望在叠加两个图像时将其考虑在内,但我不希望将第二个图像的Alpha通道添加到第一个图像。就像把一块玻璃(前景图像)放在纸张图像(背景)前面一样。
换句话说,如果背景图像是RGB而不是RGBA,则最终图像应该没有alpha信息。
答案 0 :(得分:3)
从最初的描述来看,以下想法似乎是等效的。设X,Y为两个RGBA图像。合并X和Y考虑来自X的带RGB和来自Y的RGBA带,产生图像Z.将Z中的带A设置为X中带A的带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')
函数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
这个新功能似乎考虑到了所提到的矛盾。