tcl/tk: 动画 gif 解码不正确

tcl/tk: animated gif not decoded correctly

我想在我的 Tcl/Tk 应用程序中显示一些动画 GIF(主要用于“每日提示”截屏视频)。 在 之后,我创建了这个小脚本来循环播放动画 GIF:

proc nextFrame {image {time 500} {index 0}} {
    if { [ catch {
        $image configure -format "gif -index $index"
    } stderr ] } {
        set index -1
    }
    set nextIndex [expr $index + 1]
    after $time nextFrame $image $time $nextIndex
}

set img [image create photo -file "animated.gif"]

label .w -image $img
pack .w

nextFrame $img 100

这基本可行,但遗憾的是它在正确渲染 GIF 时存在问题。

这是我用 peek 创建的动画 GIF:

例如

用我的 Tcl/Tk 脚本播放这个,我得到这个:

如您所见,存在严重的渲染问题:颜色显示错误,部分框架只是 missing/left 灰色,...)

认为 问题可能与 peek 存储动画序列的方式有关,使用一些简单的帧间压缩(通过使用子图像更新帧仅部分更改 - 我猜这在应用程序的截屏视频中非常典型)

$ identify animated.gif
animated.gif[0] GIF 895x718 895x718+0+0 8-bit sRGB 256c 0.000u 0:00.001
animated.gif[1] GIF 1x1 895x718+894+717 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[2] GIF 1x1 895x718+894+717 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[3] GIF 1x1 895x718+894+717 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[4] GIF 45x31 895x718+87+25 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[5] GIF 21x27 895x718+94+29 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[6] GIF 18x23 895x718+99+35 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[7] GIF 188x160 895x718+87+28 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[8] GIF 186x20 895x718+88+72 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[9] GIF 1x1 895x718+894+717 8-bit sRGB 256c 0.010u 0:00.002
animated.gif[10] GIF 1x1 895x718+894+717 8-bit sRGB 256c 0.010u 0:00.002

如果我通过将序列转储为 PNG (convert -coalesce animate.gif) 然后将其转换回 GIF (convert *.png) 来重新创建动画 GIF,它可以正确播放 - 但现在动画 GIF 有增长了 16 倍(2.5MB 而不是 150kB),我想避免这种情况。

关于如何正确播放具有子帧更新的动画 GIF 的任何想法?

我目前 运行 Tcl/Tk-8.6.12 Debian/sid(但我想在 macOS/Windows/Linux 上展示我的 GIF Tcl/Tk>=8.6.10

multi-partGIF图片中的图片有一点表示处理方法。此位指示新层是否应替换现有图像,或与其合并。

您的图像包含应该与现有图像合并的层,但您的代码只是切换到新层。

要合并图层,您需要两张图片,并将 GIF 中的不同图层重复复制到目标图片上:

set dir [file dirname [file normalize [info script]]]

proc nextFrame {image {time 500} {index 0}} {
    if {[catch {tmpimg configure -format "gif -index $index"} stderr]} {
        set nextIndex 0
    } else {
        set nextIndex [expr {$index + 1}]
        if {$index == 0} {
            $image copy tmpimg -compositingrule set
        } else {
            $image copy tmpimg -compositingrule overlay
        }
    }
    after $time nextFrame $image $time $nextIndex
}

set img [image create photo -file [file join $dir animated.gif]]
# Create a helper image
image create photo tmpimg -file [$img cget -file]

label .w -image $img
pack .w

nextFrame $img 100

出于某种原因,某些颜色似乎不正确,但这更接近应有的颜色。