下面的代码从两个图像创建一个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)
但是结果出乎意料的错误。第一帧很好,但随后的帧在更新区域周围包含一个黑色矩形,而不是透明度:
我认为错误如下:在第一张图像上,我们将索引255指定为完全透明的颜色的索引。但是,save
函数似乎仅将索引255转换为第一帧的透明度,但是在所有其他帧上跳过此步骤。
有什么方法可以规避PIL中的这个错误?
是的,有一种方法。 我们可以手动编辑调色板以将透明度从索引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)
结果😁