【问题标题】:Saving png sequence as WebP in pil makes background opaque black将 png 序列保存为 pil 中的 WebP 会使背景不透明变黑
【发布时间】:2022-02-19 01:42:22
【问题描述】:

问题:在Image 序列中保存为带透明度的 gif 时效果很好,但保存为 webp 时,所有帧中的透明度都丢失了。

使用:Python(最新)与 PIL(最新)

问题:如何解决?是什么原因造成的?

代码:

from PIL import Image, ImageSequence


def gen_frame(im: Image) -> Image:
    alpha = im.getchannel('A')
    # Convert the image into P mode but only use 255 colors in the palette out of 256
    im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
    # Set all pixel values below 128 to 255 , and the rest to 0
    mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
    # Paste the color of index 255 and use alpha as a mask
    im.paste(255, mask)
    # The transparency index is 255
    im.info['transparency'] = 255
    return im


im = Image.open("input_gif.gif")

im_list = []

for frame in ImageSequence.Iterator(im):
    # perform some functions on the image frames

    frame = frame.convert('RGBA').resize((512, 512), Image.ANTIALIAS)
    frame = gen_frame(frame)

    im_list.append(frame)

img = im_list[0]
imgs = im_list[1:]

img.save("output_gif.gif", save_all=True, append_images=imgs, duration=50, loop=0, optimize=False, disposal=2)
# works correctly, as intended

img.save("output_webp.webp", save_all=True, append_images=imgs, duration=50, loop=0, optimize=False, disposal=2)
# Transparency loss in the webp format

输入 gif:

输出 gif:

输出webp:

【问题讨论】:

  • 请确保您的问题最小 - 这意味着显示问题的行数尽可能少。你能用你在 6 行程序中从头开始创建的红色、绿色和蓝色图像列表来重现它吗?通常,当您删除无关材料时,您会自己发现问题。谢谢。
  • 嗯...关于您关于 WebP 的新问题,docs 说“Pillow 使用这种格式的功能的细节目前没有记录。”所以很难说哪些有效,哪些无效,以及如何使其正常运行。
  • 你能提供输入图像吗?当我将您的输出图像用作输入时,它会出现(至少在 chrome、windows 10 中)显示为白色背景,这与输入图像(您的输出图像)一致。
  • @ShanerM13 您在显示的 GIF 中看到白色背景了吗?不透明?
  • @MatrixProgrammer 是 webp 到 gif,我想要相反的

标签: python python-imaging-library


【解决方案1】:

已修复 - 您的代码确实有 1 个字符错误!

在gen_frame里面是im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255),应该是im = im.convert('RGBA').convert('P', palette=Image.ADAPTIVE, colors=255)

正确:

from PIL import Image, ImageSequence


def gen_frame(im: Image) -> Image:
    alpha = im.getchannel('A')
    # Convert the image into P mode but only use 255 colors in the palette out of 256
    # -------------------------------------------
    # THE im.convert('RGB') WAS CHANGED TO "RGBA"
    # -------------------------------------------
    im = im.convert('RGBA').convert('P', palette=Image.ADAPTIVE, colors=255)
    # Set all pixel values below 128 to 255 , and the rest to 0
    mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
    # Paste the color of index 255 and use alpha as a mask
    im.paste(255, mask)
    # The transparency index is 255
    im.info['transparency'] = 255
    return im


im = Image.open("input_gif.gif")

im_list = []

for frame in ImageSequence.Iterator(im):
    # perform some functions on the image frames

    frame = frame.convert('RGBA').resize((512, 512), Image.ANTIALIAS)
    frame = gen_frame(frame)

    im_list.append(frame)

img = im_list[0]
imgs = im_list[1:]

img.save("output_gif.gif", save_all=True, append_images=imgs, duration=50, loop=0, optimize=False, disposal=2)
# works correctly, as intended

img.save("output_webp.webp", save_all=True, append_images=imgs, duration=50, loop=0, optimize=False, disposal=2, lossless=True)
# Transparency loss in the webp format

https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif

来自文档:

GIF

Pillow 读取 GIF 文件格式的 GIF87a 和 GIF89a 版本。除非使用了 GIF89a 功能或 GIF89a 已在使用中,否则该库默认将运行长度编码文件写入 GIF87a。

GIF 文件最初被读取为灰度 (L) 或调色板模式 (P) 图像,但 寻找图像中后面的帧会将模式更改为 RGB 或 RGBA,具体取决于第一帧是否具有透明度

所以本质上,当您为图像生成帧时,尽管在信息属性中设置了透明度,但您并没有添加 Alpha 通道,当您保存它时,它就丢失了。

根据文档:

透明度

透明色指数。如果图像不透明,则省略此键。

【讨论】:

    猜你喜欢
    • 2019-12-09
    • 1970-01-01
    • 2014-11-12
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 2021-10-03
    • 1970-01-01
    相关资源
    最近更新 更多