I found that I needed to copy bitmap image data into a photo image. Since photo doesn't like bitmap data, I wrote up a little XBM reader that does the job. This may be completely pointless, but here it is anyway.
The first proc simply creates a photo image with the same arguments as the "image create bitmap" command takes (except you cannot name the resulting image).
proc image.create.xbm args { array set a $args if {[array names a -exact -file] ne {}} { set fid [open $a(-file) r] set a(-data) [read $fid] close $fid } if {[array names a -exact -maskfile] ne {}} { set fid [open $a(-maskfile) r] set a(-maskdata) [read $fid] close $fid } if {[array names a -exact -foreground] eq {}} {set a(-foreground) black} if {[array names a -exact -background] eq {}} {set a(-background) {}} if {$a(-background) eq {}} { set a(-maskdata) $a(-data) set a(-background) white } set width [lindex [regexp -inline -- {width\s+(\d+)} $a(-data)] 1] set height [lindex [regexp -inline -- {height\s+(\d+)} $a(-data)] 1] set result [image create photo -width $width -height $height] regexp -indices -- {\{\s*(0x[^\}]*)} $a(-data) r1 range foreach {b e} $range break set data [join [split [string trim [string range $a(-data) $b $e]] ,]] set line {} set ycntr0 0 set ycntr1 1 foreach datum $data { foreach cntr {0 1 2 3 4 5 6 7} { if {($datum %2) == 0} \ then {lappend line $a(-background)} \ else {lappend line $a(-foreground)} set datum [expr {$datum >> 1}] } if {[llength $line] >= $width} { $result put [list $line] -to 0 $ycntr0 $width $ycntr1 incr ycntr0 incr ycntr1 set line {} } } if {[array names a -exact -maskdata] ne {}} { set w [lindex [regexp -inline -- {width\s+(\d+)} $a(-data)] 1] set h [lindex [regexp -inline -- {height\s+(\d+)} $a(-data)] 1] if {($w != $width) || ($h != $height)} { error {bitmap and mask have different sizes} } regexp -indices -- {\{\s*(0x[^\}]*)} $a(-maskdata) r1 range foreach {b e} $range break set data [join [split [string trim [string range $a(-maskdata) $b $e]] ,]] set ycntr 0 set xcntr 0 foreach datum $data { foreach cntr {0 1 2 3 4 5 6 7} { if {($datum %2) == 0} { $result transparency set $xcntr $ycntr true } set datum [expr {$datum >> 1}] incr xcntr if {$xcntr >= $width} { incr ycntr set xcntr 0 break } } } } return $result }
This next proc takes a bitmap image and returns a photo image.
proc image.bitmap.to.photo bmp { set options {} foreach opt {-background -data -file -foreground -maskdata -maskfile} { lappend options $opt [$bmp cget $opt] } return [eval image.create.xbm $options] }
If you're using Tcl/Tk 8.5+ you can change that last line to
return [image.create.xbm {*}$options]
Duoas 2007-05-07 22:03
2009-10-26 17:14 I don't ever remember not making a comment here... but anyway...
The above proc fails if your bitmap does not have a mask. A simple update:
proc image.bitmap.to.photo bmp { set options {} foreach opt {-background -data -file -foreground -maskdata -maskfile} { set val [$bmp cget $opt] if {$val ne {}} { lappend options $opt $val } } return [eval image.create.xbm $options] }
Not as pretty, I know... but it works.