在 pil 中将 png 序列保存为 WebP 会使背景不透明黑色
Saving png sequence as WebP in pil makes background opaque black
问题:当在 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:
已修复 - 您的代码实际上有 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 reads GIF87a and GIF89a versions of the GIF file format. The library writes run-length encoded files in GIF87a by default, unless GIF89a features are used or GIF89a is already in use.
GIF files are initially read as grayscale (L) or palette mode (P) images, but seeking to later frames in an image will change the mode to either RGB or RGBA, depending on whether the first frame had transparency.
所以本质上,当您为图像生成帧时,尽管在信息属性中设置了透明度,但您并没有向其添加 alpha 通道,当您保存它时,它丢失了.
根据文档:
transparency
Transparency color index. This key is omitted if the image is not transparent.
问题:当在 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:
已修复 - 您的代码实际上有 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 reads GIF87a and GIF89a versions of the GIF file format. The library writes run-length encoded files in GIF87a by default, unless GIF89a features are used or GIF89a is already in use.
GIF files are initially read as grayscale (L) or palette mode (P) images, but seeking to later frames in an image will change the mode to either RGB or RGBA, depending on whether the first frame had transparency.
所以本质上,当您为图像生成帧时,尽管在信息属性中设置了透明度,但您并没有向其添加 alpha 通道,当您保存它时,它丢失了.
根据文档:
transparency
Transparency color index. This key is omitted if the image is not transparent.