[AMG]: I collected code from other Wiki pages on reading image dimensions of various formats ([GIF], [PNG], [JPEG], and [BMP]) and made a single [proc] that can determine the type and dimensions all at once. The argument is the name of the [channel] connected to the image data. The image is expected to begin at the current channel [seek] position, and the channel must have "binary" translation. The returned value is a one- or three-element [list]. The first element is the type, which is gif, png, jpeg, bmp, or unknown. The second and third elements are the image width and height in pixels; they're omitted if the first element is unknown. ====== proc imageinfo {chan} { set tell [chan tell $chan] if {[chan read $chan 16] eq "\211PNG\r\n\32\n\0\0\0\rIHDR"} { set type png binary scan [chan read $chan 8] II width height } elseif {"[chan seek $chan $tell][chan read $chan 6]" in {GIF87a GIF89a}} { set type gif binary scan [chan read $chan 4] ss width height } elseif {"[chan seek $chan $tell][chan read $chan 2]" eq "\377\330"} { set type jpeg while {![chan eof $chan]} { while {[chan read $chan 1] ne "\377"} {} while {[set byte [chan read $chan 1]] eq "\377"} {} if {$byte in {\300 \301 \302 \303 \305 \306 \307 \311 \312 \313 \315 \316 \317}} { binary scan [chan read $chan 7] x3SS height width break } else { binary scan [chan read $chan 2] S offset chan seek $chan [expr {($offset & 0xffff) - 2}] current } } } elseif {"[chan seek $chan $tell][chan read $chan 2]" eq "BM"} { set type bmp binary scan [chan read $chan 24] x16ii width height } if {[info exists type] && [info exists width] && [info exists height]} { list $type [expr {$width & 0xffff}] [expr {$height & 0xffff}] } else { list unknown } } ====== I designed it for use with the [SQLite] [[$db incrblob]] command, which produces a channel providing incremental access to a database blob. It's also suitable for use with ordinary file I/O. Remember to [close] the channel when you're done with it. Here's a version that operates directly on the image data: ====== proc imageinfo {data} { if {[string equal -length 16 $data \211PNG\r\n\32\n\0\0\0\rIHDR]} { set type png binary scan [string range $data 16 23] II width height } elseif {[string range $data 0 5] in {GIF87a GIF89a}} { set type gif binary scan [string range $data 6 9] ss width height } elseif {[string equal -length 2 $data \377\330]} { set type jpeg set pos 2 while {[regexp -start $pos {\377([^\377])(.{2,7})} $data _ mark args]} { if {$mark in {\300 \301 \302 \303 \305 \306 \307 \311 \312 \313 \315 \316 \317}} { binary scan $args x3SS height width break } else { binary scan $args S offset set pos [expr {$pos + ($offset & 0xffff) - 2}] } } } elseif {[string equal -length 2 $data BM]} { set type bmp binary scan [string range $data 18 25] ii width height } if {[info exists type] && [info exists width] && [info exists height]} { list $type [expr {$width & 0xffff}] [expr {$height & 0xffff}] } else { list unknown } } ====== ---- **See also** * [Reading GIF image dimensions] * [Reading PNG image dimensions] * [Reading JPEG image dimensions] * [Reading BMP image dimensions] <> Graphics | File