AniGif: | animated GIF-Images |
Where: | http://cardtable.go.to/tcltk/ |
Mirrored here: | http://cardtable.sourceforge.net/tcltk/ |
Description: | Tk extension allowing you to create, start, stop, restart and destroy animated GIFs. Supports single play images as well as images without full image data on each frame. Use gifsicle to uncompress compressed/interlaced GIFs before subsequent processing. |
Currently at version 1.3. | |
Updated: | 03/2002 |
Contact: | mailto:[email protected] |
Is "animated gif" somehow a Windows-specific notion? Modern Mac OS X opens animated gif-s with Preview, and Preview does not appear to animate.
Lars H: I don't think it's Windows-specific, but I recall seeing the animation feature descibed as a bit of an oddity. Try opening in a web browser instead; I see the test animation on this page fine in Safari. It's possible that Preview lets you view each frame of the gif as a still image instead.
The Tk code which follows, of course, executes and displays quite nicely on all platforms.
Note that it does not read the delay time out of the gif — it appears that Img does not provide such metadata. Fortunately here on the wiki is gifblock which can be used.
SeS 2015-08-17: Looking into the format description of a .gif , I can tell that I need to search for the first 21 F9 data pattern in the file. The next two bytes we can ignore, the 2 bytes following is the frame rate. Based on my assumption, that this is the correct way to extract the frame rate, here the tcl solution:
proc getGifFrameRate {file} { set d 0 set i 0 set f [open $file r] fconfigure $f -translation binary while {$i<1000} { binary scan [read $f 2] s B1 if {$B1 == -1759} { binary scan [read $f 2] s B1 binary scan [read $f 2] s d break } incr i } close $f return $d }
Not sayin this is the best way or fastest or whatever, just a quick and dirty method which works for me and the majority of .gif files I used to test it on. The returned value * 10ms is the frame rate in the file. Returns 0 if .gif is not an animated one.
RS 2004-07-27: Also, in plain Tk (but documented only for Img), you have access to the partial images of an animated GIF. This code was enough for me:
package require Img proc anigif file { #-- returns a list of images from the given GIF file set index 0 set results {} while 1 { if [catch { image create photo -file $file -format "gif -index $index" } res] { return $results } lappend results $res incr index } } #-- Testing (dumping the animation phases, one next to the other, into a text widget):
Test image:
#-- Testing (dumping the animation phases into a text widget, and an animation): proc lcycle listName { upvar 1 $listName list set res [lindex $list 0] set list [concat [lrange $list 1 end] [list $res]] set res } proc every {ms body} {eval $body; after $ms [namespace code [info level 0]]} set file [lindex $argv 0] pack [text .t] set images [anigif $file] foreach img $images { .t image create end -image $img } .t insert end animated: set id [.t image create end -image [lindex $images 0]] every 100 ".t image config $id -image \[lcycle ::images\]"
Here's a slightly more minimal-but-generalizable form, applied to a canvas:
proc animate_in_canvas {canvas gif} { global id_list # As written, there's only room for a single animation at a time. set id_list {} foreach img [anigif $gif] { lappend id_list [.c create image 0 0 -anchor nw -image $img] } every 150 ".c raise \[lcycle ::id_list\]" } pack [canvas .c -height 300 -width 300] animate_in_canvas .c [lindex $argv 0]
#apply to a label proc play {ms lbl img_list} { set img [lindex [$lbl config -image] end] set idx [lsearch $img_list $img] incr idx if {$idx > [llength $img_list] - 1} { set idx 0 } $lbl config -image [lindex $img_list $idx] after $ms "play $ms $lbl \"$img_list\"" } set img_list [anigif d:/dummy/ss.gif] label .l -image [lindex $img_list 0] pack .l play 100 .l $img_list
rahulj: what about destroying animated gif canvas or label?
SeS 2015-08-15:
hey rahulj, not 100% sure if I understood your question, but if it is what I think, then I propose the following mod in proc play:
if {[catch {set img [lindex [$lbl config -image] end]}]} {return}
This will effectively stop the play procedure in case the label is destoyed.
SeS 2015-08-21:
See also : tG2 .gif animation wrapper