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
出于某种原因,某些颜色似乎不正确,但这更接近应有的颜色。
我想在我的 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
出于某种原因,某些颜色似乎不正确,但这更接近应有的颜色。