|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 [GIF]s. Supports single play [image]s 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:scfiead_spammenot@hotmail.com| ---- 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] Aug. 17th, 2015 Looking into the https://en.wikipedia.org/wiki/GIF%|%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): ====== [WikiDbImage anigif.jpg] Test image: [WikiDbImage underconstruction.gif] ====== #-- 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 [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] ====== ---- [mzgcoco] ====== #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] 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. <> Package | Animation | Graphics