Animer une image GIF

 

ulis, 2005-09-17. Une procédure qui anime une image GIF.

2005-09-19, maj : Prise en compte du delai enregistré dans le fichier GIF.

(animation par le navigateur)


Pourquoi

Pour animer Tcl/Tk tiens !


Comment

En affichant successivement les images d'un fichier GIF.


La procédure

  namespace eval ::animate \
  {
    array set bits4 \
    {
      0000  0
      0001  1
      0010  2
      0011  3
      0100  4
      0101  5
      0110  6
      0111  7
      1000  8
      1001  9
      1010  10
      1011  11
      1100  12
      1101  13
      1110  14
      1111  15
    }
  }

  proc animate {file script} \
  {
    # read file
    set fn $file
    set fp [open $fn]
    fconfigure $fp -translation binary
    set data [read $fp]
    close $fp
    # check
    if {[string range $data 0 3] != "GIF8"} \
    { error "'$file' is not a GIF file" }
    # build header
    set p 5
    set chunk [string range $data 6 12]
    binary scan $chunk ttB8H2c width height map bg zero
    set bpp $::animate::bits4([string range $map 4 end])
    set gmsize 0
    if {[string index $map 0] == "1"} \
    { set gmsize [expr {2 << $bpp}] }
    set p [expr {13 + 3 * $gmsize}]
    set header [string range $data 0 [expr {$p - 1}]]
    # build images
    set ::animate::$file.num 0
    while 1 \
    {
      switch -exact -- [string index $data $p] \
      {
        !   \
        {
          # extension
          incr p
          binary scan [string index $data $p] H2 function
          incr p
          while 1 \
          {
            binary scan [string index $data $p] c count
            incr p
            if {$count == 0} { break }
            if {$count < 0} { set count [expr {256 + $count}] }
            if {$function == "f9"} \
            {
              # get delay
              binary scan [string index $data [expr {$p + 1}]] c delay
              set ::animate::$file.delay([set ::animate::$file.num]) $delay
            }
            incr p $count
          }
        }
        ,   \
        {
          # image
          puts image
          set pi $p
          incr p
          set chunk [string range $data $p [expr {$p + 9}]]
          binary scan $chunk ttttB8 left top width height map
          set bpp $::animate::bits4([string range $map 4 end])
          set lmsize 0
          if {[string index $map 0] == "1"} \
          { set lmsize [expr {2 << $bpp}] }
          incr bpp
          incr p [expr {10 + 3 * $lmsize}]
          while 1 \
          {
            binary scan [string index $data $p] c count
            incr p
            if {$count == 0} { break }
            if {$count < 0} { set count [expr {256 + $count}] }
            incr p $count
          }
          set img $header[string range $data $pi [expr {$p - 1}]];
          set ::animate::$file.img([set ::animate::$file.num]) [image create photo -data $img]
          incr ::animate::$file.num
        }
        ;   \
        {
          # end of file
          break
        }
      }
    }
    # build animate proc
    proc ::animate::$file.step {script file step} \
    {
      set delay [set ::animate::$file.delay($step)]
      set delay [expr {$delay * 10}]
      set curstep $step
      incr step
      if {$step == [set ::animate::$file.num]} { set step 0 }
      after $delay [list ::animate::$file.step $script $file $step]
      after $delay $script [set ::animate::$file.img($curstep)]
      update
    }
    # animate
    ::animate::$file.step $script $file 0
  }

Le test

  # package
  package require Tk

  # animate markachis & smaguy
  pack [canvas .c]
  .c create image 0 0 -anchor nw -tags animated
  pack [canvas .d]
  .d create image 0 0 -anchor nw -tags animated
  animate markachis.gif {.c itemconfig animated -image}
  animate smaguy.gif {.d itemconfig animated -image}

Voir ausssi

(à compléter)


Discussion


Catégorie Exemple | Catégorie Traitement d'image