skip to Main Content

I’d like to show some animated GIFs (mostly for "Tip-of-the-Day" screencasts) in my Tcl/Tk application.
Following https://stackoverflow.com/a/28797669/1169096, I’ve created this small script to play back an animated GIF in a loop:

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

This basically works, but unfortunately it has problems with rendering the GIFs correctly.

Here’s an animaged GIF i created with peek:

E.g. original screencast

Playing this back with my Tcl/Tk script, i get this:

broken playback

As you can see, there are severe rendering issues: colors are displayed wrongly, parts of the frames are simply missing/left grey,…)

I think the problem might be related to the way peek stores the animation sequence, using some simple inter-frame compression (by using subimages to update frames that only partially change – something quite typical in screencasts of applications, i guess)

$ 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

If I recreate the animated GIF by dumping the sequence to PNG (convert -coalesce animate.gif) and then convert it back to GIF (convert *.png), it plays back correctly – but now the animated GIF has grown by a factor of 16 (2.5MB instead of 150kB), which I would like to avoid.

Any ideas how to correctly play back an animated GIF that has subframe updates?

I’m currently running Tcl/Tk-8.6.12 on Debian/sid (but I’d like to show my GIFs on macOS/Windows/Linux with Tcl/Tk>=8.6.10

2

Answers


  1. The images in a multi-part GIF image have a bit indicating the disposal method. This bit indicates whether the new layer should replace the existing image, or be combined with it.

    Your image contains layers that are supposed to be combined with the existing image, but your code simply switches to the new layer.

    To combine the layers, you would need two images, and repeatedly copy the different layers from the GIF onto the target image:

    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
    

    For some reason some colors seem to be off, but this comes much closer to what it should be.

    Login or Signup to reply.
  2. The relevant Tk ticket now has an implementation to get the eventual missing information in the Tk8.7 metadata framework.
    I would appreciate a review. It will unfortunately not help you with Tk 8.6.10, as this may be included in Tk 8.7b1.

    Thank you and take care,
    Harald

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search