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

以下代码从两个图像创建一个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)

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

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

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

有什么办法可以避免这种情况?

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

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

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

在最坏的情况下(例如彩色长GIF),透明度并不总是位于索引255上,我们必须手动将其与索引0对齐(请参见shiftme行)。

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()

# if you know a data point in the resulting image that will be
# transparent you can also set it directly e.g. 'shiftme = -frame[0][0]'
shiftme = 1       
im1 = (numpy.array(im1) + shiftme) % 256  # shift data pointing into palette
im2 = (numpy.array(im2) + shiftme) % 256

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

im1.putpalette( p1[-3*shiftme:] + p1[:-3*shiftme] )  # shift palette
im2.putpalette( p2[-3*shiftme:] + p2[:-3*shiftme] )  # NB this is NOT '-4' as it is RGB not 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

,

除了我的其他答案外,您还可以set the disposal value

im1.save('output.gif',transparency=255,disposal=2)

请注意,与我的其他答案不同,这不能100%地起作用,因为透明度通道可以跳转到其他索引。 :-/但是,这似乎只发生在具有许多颜色的较长GIF中。

左:此答案,右:其他手动对齐的答案

example of bug persisting example of bug fixed

本文链接:https://www.f2er.com/2773273.html

大家都在问