python – 使用PIL缩放图像保持透明度和颜色?

假设您想缩放透明图像但尚不知道背景的颜色,您将在以后合成它.不幸的是,PIL似乎包含完全透明像素的颜色值,导致不良结果.有没有办法告诉PIL-resize忽略完全透明的像素?

import PIL.Image

filename = "trans.png"  # http://qrc-designer.com/stuff/trans.png
size = (25,25)

im = PIL.Image.open(filename)
print im.mode  # RGBA

im = im.resize(size, PIL.Image.LINEAR)  # the same with CUBIC, ANTIALIAS, transform
# im.show()  # does not use alpha
im.save("resizelinear_"+filename)


# PIL scaled image has dark border

原始图像与(0,0,0,0)(黑色但完全透明)背景(左)

输出图像与黑色光环(中)

使用gimp缩放适当的输出(右)

编辑:它看起来像实现我正在寻找的东西我将不得不修改调整大小函数本身的采样,这样它将忽略具有完全透明度的像素.

edit2:我发现了一个非常难看的解决方案.它将完全透明像素的颜色值设置为周围非完全透明像素的平均值,以最小化完全透明像素颜色在调整大小时的影响.它在简单的形式中很慢,但如果没有其他解决方案,我会发布它.通过使用扩张操作来处理必要的像素,可能会使其更快.

edit3:预乘alpha是要走的路 – 看Mark的回答

最佳答案
似乎PIL在调整大小之前不进行alpha预乘,这对于获得正确的结果是必要的.幸运的是,蛮力很容易做到.然后,您必须反向调整大小的结果.

def premultiply(im):
    pixels = im.load()
    for y in range(im.size[1]):
        for x in range(im.size[0]):
            r, g, b, a = pixels[x, y]
            if a != 255:
                r = r * a // 255
                g = g * a // 255
                b = b * a // 255
                pixels[x, y] = (r, g, b, a)

def unmultiply(im):
    pixels = im.load()
    for y in range(im.size[1]):
        for x in range(im.size[0]):
            r, g, b, a = pixels[x, y]
            if a != 255 and a != 0:
                r = 255 if r >= a else 255 * r // a
                g = 255 if g >= a else 255 * g // a
                b = 255 if b >= a else 255 * b // a
                pixels[x, y] = (r, g, b, a)

结果:

转载注明原文:python – 使用PIL缩放图像保持透明度和颜色? - 代码日志