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

2024-03-12

假设您想要缩放透明图像,但还不知道稍后将其合成的背景颜色。不幸的是,PIL 似乎合并了完全透明像素的颜色值,导致了糟糕的结果。有没有办法告诉 PIL-resize 忽略完全透明的像素?

import PIL.Image

filename = "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 缩放的正确输出(右)

看起来要实现我正在寻找的目标,我必须修改调整大小函数本身的采样,以便它忽略完全透明的像素。

我找到了一个非常丑陋的解决方案。它将完全透明像素的颜色值设置为周围非完全透明像素的平均值,以最大限度地减少调整大小时完全透明像素颜色的影响。简单的形式很慢,但如果没有其他解决方案,我会发布它。通过使用扩张操作仅处理必要的像素,可能可以使其更快。


看来 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)

Result: result of premultiply, resize, unmultiply

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 PIL 缩放图像并保持透明度和颜色? 的相关文章

随机推荐