Note that this is still very much a work-in-progress as I (
DKF) am not putting much time into working on this. :^)
package req Tk
proc load {file} {
image create photo foo -file $file
set w [image width foo]
set h [image height foo]
# Construct basic RLE data from image (assumed monochrome)
set init 0
set length 0
set out [list $w $h]
set max [expr {$w>$h ? $w : $h}]
for {set x 0} {$x<$w} {incr x} {
for {set y 0} {$y<$h} {incr y} {
set item [expr {[lindex [foo get $x $y] 0] > 127}]
if {$item != $init} {
lappend out $length
if {$max < $length} {
set max $length
}
set init $item
set length 0
}
incr length
}
}
if {$max < $length} {
set max $length
}
lappend out $length
image delete foo
return [list $max $out]
}
proc compress {file} {
foreach {max data} [load $file] break
set bits [expr {(int(ceil(log($max)/log(2)))>>1) + 1}]
set limit [expr {1<<$bits}]
# If the chunk size doesn't fit in 4 bits, we're in trouble.
binary scan [binary format i $bits] b4 output
foreach val $data {
if {$val < $limit} {
binary scan [binary format i $val] b$bits binary
append output $binary
} else {
set v1 [expr {$val & ($limit-1)}]
set v2 [expr {$val >> $bits}]
binary scan [binary format i $v1] b$bits b1
binary scan [binary format i $v2] b$bits b2
append output $b1[string repeat 0 $bits]$b2
}
}
return [binary format b* $output]
}
proc gzip d {
set data [open foo.tmp w]
fconfigure $data -translation binary
puts -nonewline $data $d
close $data
set f [open "|gzip -c <foo.tmp" r]
fconfigure $f -translation binary
set d [read $f]
close $f
after 100 ;# Ugly hack to give gzip time to exit so we can kill foo.tmp on Windows
file delete foo.tmp
return $d
}
set files [lsort [glob *.gif]]
pack [text .t -font {courier 12} -height [expr {[llength $files]+1}]]
set w [font measure {Courier 12} "File: "]
foreach f $files {
set w2 [font measure {Courier 12} "[file tail $f] "]
if {$w2 > $w} {
set w $w2
}
}
.t conf -tab "$w left [expr $w+100]"
.t insert end "File:\tPrior\tPost\tgzipped\tTimings\n"
foreach f $files {
set t [time {set d [compress $f]}]
set d2 [gzip $d]
.t insert end "[file tail $f]\t[file size $f]\t[string length $d]\t[string length $d2]\t$t\n"
}