PIL将两个图像与alpha通道合并 - 未按预期工作

时间:2012-12-06 18:50:10

标签: 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")

这两张图片是:

背景

Background

前景

Foreground

预期输出

Expected output

实际结果

Actual result

如果你没有看到差异,这里是最终版本的alpha通道(倒置以便更好地显示)。

预期结果 - Alpha通道

Expected result - alpha channel

实际结果 - Alpha通道

Actual result - alpha channel

所以说,有没有办法做到这一点,或者我做错了什么?

编辑 - 在@zenpoy评论之后澄清:

如果前景图像具有一定的不透明度,我希望在叠加两个图像时将其考虑在内,但我不希望将第二个图像的Alpha通道添加到第一个图像。就像把一块玻璃(前景图像)放在纸张图像(背景)前面一样。

换句话说,如果背景图像是RGB而不是RGBA,则最终图像应该没有alpha信息。

1 个答案:

答案 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

这个新功能似乎考虑到了所提到的矛盾。