Updated 2007-07-02 18:49:52 by kbk

2007-05-18 VI PCX is an image format used by old versions of paintbrush. http://courses.ece.uiuc.edu/ece390/books/labmanual/graphics-pcx.html and http://www.qzx.com/pc-gpe/pcx.txt are good references.

This proc just takes 2 filenames, an input pcx and an output gif filename. Requires just Tcl and Tk. I have tested it only for 8-bitsperpixel though there is code for 1,2 and 4 bits per pixel

e.g.
 pcx2gif P2007_0517_1042.pcx PQ.gif

 proc scan1 {fi} { binary scan [read $fi 1] c val; return [expr {$val & 0xFF}] }
 proc scan2 {fi} { binary scan [read $fi 2] s val; return [expr {$val & 0xFFFF}] }

 proc pcx2gif {pcxfn giffn} {
    set header {
	manufacturer 1
	version      1
	encoding     1
	bitsperpixel 1
	xmin         2
	ymin         2
	xmax         2
	ymax         2
	horizdpi     2
	vertdpi      2
	palette     48
	rsvd1        1
	colorplanes  1
	bytesperline 2
	palettetype  2
	hscrsize     2
	vscrsize     2
	filler      54
    }
    set fi [open $pcxfn r]
    fconfigure $fi -translation binary

    foreach {name len} $header {
	switch $len {
	    1 {set pcx($name) [scan1 $fi]}
	    2 {set pcx($name) [scan2 $fi]}
	    default {set pcx($name) [read $fi $len]}
	}
    }

    if {$pcx(manufacturer) != 10 } {error "Manufacturer is not 1"}
    if {$pcx(encoding) != 1} {error "Encoding is not 1"}
    switch $pcx(bitsperpixel) {
	1 {set p2c(0) \#000000;set p2c(1) \#FFFFFF}
	2 - 4 {
	    if {$pcx(bitsperpixel) == 2} {
		set bytes 12
	    } else {
		set bytes 48
	    }
	    binary scan $pcx(palette) c$bytes l
	    set i 0
	    foreach {r g b} $l {
		set p2c($i) [format "#%02X%02X%02X" $r $g $b]
		incr i
	    }
	}
	8 {
	    set pos [tell $fi]
	    seek $fi -769 end
	    if {[scan1 $fi] != 12} {
		error "No palette found"
	    }
	    for {set i 0} {$i < 256} {incr i} {
		set p2c($i) [format "#%02X%02X%02X" [scan1 $fi] [scan1 $fi] [scan1 $fi]]
	    }
	    seek $fi $pos
	}
    }

    set image [list]
    for {set row $pcx(ymin)} {$row <= $pcx(ymax)} {incr row} {
	set line [list]
	for {set col $pcx(xmin)} {$col <= $pcx(xmax)} {incr col} {
	    set c [scan1 $fi]
	    if {$c >= 192} {		#found length byte
		set len [expr $c & 0x3F]
		set pxl $p2c([scan1 $fi])
		for {set i 0} {$i < $len} {incr i} {
		    lappend line $pxl
		    incr col
		}
		incr col -1
	    } else {
		lappend line $p2c($c)
	    }
	}
	lappend image $line
    }

    image create photo pic -height [expr $pcx(ymax) - $pcx(ymin) + 1] \
	-width [expr $pcx(xmax) - $pcx(ymin) + 1]
    pic put $image
    pic write $giffn -format gif
 }