动画GIF仅在其第一帧上是透明的(Python PIL)

问题描述 投票:0回答:1

下面的代码从两个图像创建一个GIF:

# GIFs are always palette images so they would be converted later anyway
im1 = PIL.Image.open('grin-emoji-by-twitter-rgba.png').convert('P')
im2 = PIL.Image.open('grin-emoji-by-twitter-rgba-2.png').convert('P')

im1.save('output.gif', save_all=True, append_images=[im2, im1, im2], loop=0, duration=200, transparency=255)

但是结果出乎意料的错误。第一帧很好,但随后的帧在更新区域周围包含一个黑色矩形,而不是透明度:

enter image description here

我认为错误如下:在第一张图像上,我们将索引255指定为完全透明的颜色的索引。但是,save函数似乎仅将索引255转换为第一帧的透明度,但是在所有其他帧上跳过此步骤。

有什么方法可以规避PIL中的这个错误?

python python-imaging-library transparency animated-gif
1个回答
0
投票

是的,有一种方法。 我们可以手动编辑调色板以将透明度从索引255移到0。如果透明度位于索引0而不是255,则save不会表现异常。

我通过将整个调色板右移一个索引来完成此操作,因此索引5变成索引6,索引255变成索引0,依此类推:]等等>

im1 = PIL.Image.open('grin-emoji-by-twitter-rgba.png').convert('P')
im2 = PIL.Image.open('grin-emoji-by-twitter-rgba-2.png').convert('P')

p1 = im1.getpalette()
p2 = im2.getpalette()

im1 = (numpy.array(im1) + 1) % 256  # shift data pointing into palette
im2 = (numpy.array(im2) + 1) % 256

im1 = PIL.Image.fromarray( im1 ).convert('P')
im2 = PIL.Image.fromarray( im2 ).convert('P')

im1.putpalette( p1[-3:] + p1[:-3] )  # shift palette
im2.putpalette( p2[-3:] + p2[:-3] )  # NB this is NOT '-4' as one might expect from RGBA

print(numpy.array(im1))
print(numpy.array(im2))

im1.save('output.gif', save_all=True, append_images=[im2, im1, im2], loop=0, duration=200, transparency=0)

结果😁

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.