【问题标题】:Animated GIFs are only transparent on their first frame (Python PIL)动画 GIF 仅在其第一帧上是透明的(Python PIL)
【发布时间】:2020-04-30 22:21:42
【问题描述】:

以下代码从两个图像创建一个 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 转换为透明度,但在所有其他帧上跳过这一步。

有什么办法可以避免吗?

【问题讨论】:

    标签: python python-imaging-library transparency animated-gif


    【解决方案1】:

    是的,有办法。 我们可以手动编辑调色板以将透明度从索引 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)
    

    结果?

    【讨论】:

      【解决方案2】:

      作为我其他答案的替代方案,您也可以set the disposal value to 2

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

      请注意,与我的其他答案不同,这并不是 100% 的时间,因为透明度通道可以跳转到其他索引。 :-/ 然而,这似乎只发生在较长的 GIF 中,其中包含许多颜色。

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

      编辑:Here 据称在较新版本的枕头中已修复! (我认为是 8.1.2+)

      【讨论】:

        猜你喜欢
        • 2012-01-03
        • 2019-08-28
        • 2014-06-10
        • 2014-12-16
        • 2012-06-12
        • 2021-03-17
        • 1970-01-01
        • 2012-04-16
        • 2023-03-03
        相关资源
        最近更新 更多