--- a/PCXReader.st Fri Apr 04 19:07:10 2003 +0200
+++ b/PCXReader.st Fri Apr 04 19:07:54 2003 +0200
@@ -13,7 +13,7 @@
"{ Package: 'stx:libview2' }"
ImageReader subclass:#PCXReader
- instanceVariableNames:''
+ instanceVariableNames:'header buffer nBuffer bufferIndex sourceBytesPerRow'
classVariableNames:''
poolDictionaries:''
category:'Graphics-Images-Support'
@@ -52,6 +52,12 @@
ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader
XBMReader XPMReader XWDReader
"
+!
+
+examples
+"
+ Image fromFile:'/usr/share/lilo/suse_640x480.pcx'
+"
! !
!PCXReader class methodsFor:'initialization'!
@@ -108,54 +114,163 @@
!PCXReader methodsFor:'reading from file'!
-fromStream:aStream
- "read an image in pcx format from aStream"
+extractColorMap16
+ "extract the 16-entry colormap from the header"
+
+ |rawMap srcIndex rMap gMap bMap|
+
+ rawMap := ByteArray uninitializedNew:(16*3).
+ rawMap replaceFrom:1 to:(16*3) with:header startingAt:17.
+ rMap := ByteArray new:16.
+ gMap := ByteArray new:16.
+ bMap := ByteArray new:16.
+ srcIndex := 1.
+ 1 to:16 do:[:i |
+ |r g b|
+
+ r := rawMap at:srcIndex.
+ g := rawMap at:srcIndex+1.
+ b := rawMap at:srcIndex+2.
+
+ rMap at:i put:r.
+ gMap at:i put:g.
+ bMap at:i put:b.
+ srcIndex := srcIndex + 3.
+ ].
+ ^ Colormap redVector:rMap greenVector:gMap blueVector:bMap.
+!
+
+nextByteFromBufferOrStream
+ |byte|
+
+ nBuffer ~~ 0 ifTrue:[
+ byte := buffer at:bufferIndex.
+ bufferIndex := bufferIndex + 1. nBuffer := nBuffer - 1.
+ ] ifFalse:[
+ byte := inStream next
+ ].
+ ^ byte
+!
+
+readColorMap256
+ |rawMap mapSize rMap gMap bMap srcIndex|
+
+ rawMap := ByteArray uninitializedNew:(256*3).
+ nBuffer ~~ 0 ifTrue:[
+ mapSize := buffer size - bufferIndex + 1.
+ mapSize := mapSize min:(256*3).
+ rawMap replaceFrom:1 to:mapSize with:buffer startingAt:bufferIndex.
+ nBuffer < (256*3) ifTrue:[
+ inStream nextBytes:((256*3)-nBuffer) into:rawMap startingAt:nBuffer+1
+ ]
+ ] ifFalse:[
+ inStream nextBytes:(256*3) into:rawMap.
+ ].
+ rMap := Array new:256.
+ gMap := Array new:256.
+ bMap := Array new:256.
+ srcIndex := 1.
+
+ 1 to:256 do:[:i |
+ |r g b|
+
+ r := rawMap at:srcIndex.
+ g := rawMap at:srcIndex+1.
+ b := rawMap at:srcIndex+2.
- |fileSize header img|
+ rMap at:i put:r.
+ gMap at:i put:g.
+ bMap at:i put:b.
+ srcIndex := srcIndex + 3.
+ ].
+
+ ^ Colormap redVector:rMap greenVector:gMap blueVector:bMap.
+!
+
+readCompressedData
+ |bendIndex rowIndex dstIndex endIndex byte nByte value idx2
+ srcIndex|
+
+ data := ByteArray uninitializedNew:(height * sourceBytesPerRow).
+
+ buffer := ByteArray uninitializedNew:4096.
+ bufferIndex := 1.
+ bendIndex := 1.
- inStream := aStream.
+ rowIndex := 1.
+ 1 to:height do:[:row |
+ dstIndex := rowIndex.
+ endIndex := dstIndex + sourceBytesPerRow.
+ [dstIndex < endIndex] whileTrue:[
+ bufferIndex == bendIndex ifTrue:[
+ nBuffer := inStream nextBytes:4096 into:buffer.
+ bufferIndex := 1.
+ bendIndex := nBuffer + 1.
+ ].
+ byte := buffer at:bufferIndex.
+ bufferIndex := bufferIndex + 1.
+ ((byte bitAnd:2r11000000) ~~ 2r11000000) ifTrue:[
+ data at:dstIndex put:byte.
+ dstIndex := dstIndex + 1.
+ ] ifFalse:[
+ nByte := byte bitAnd:2r00111111.
+ bufferIndex == bendIndex ifTrue:[
+ nBuffer := inStream nextBytes:4096 into:buffer.
+ bufferIndex := 1.
+ bendIndex := nBuffer + 1.
+ ].
+ value := buffer at:bufferIndex.
+ bufferIndex := bufferIndex + 1.
+ idx2 := ((dstIndex + nByte) min:endIndex) - 1.
+ data from:dstIndex to:idx2 put:value.
+ dstIndex := dstIndex + nByte.
+ ].
+ ].
+ rowIndex := endIndex.
+ ].
+
+ "/ have to compress - above code reads sourceBytesPerRow
+ "/ (to keep in sync with RLE); but we want width bytesPerRow
+ "/ Can compress in the data-area; leftover pixels are simply ignored
+ "/ by other image processing code
+ "/
+ sourceBytesPerRow ~~ width ifTrue:[
+ dstIndex := width + 1.
+ srcIndex := sourceBytesPerRow + 1.
+ 2 to:height do:[:row |
+ data replaceFrom:dstIndex to:dstIndex+width-1 with:data startingAt:srcIndex.
+ dstIndex := dstIndex + width.
+ srcIndex := srcIndex + sourceBytesPerRow
+ ]
+ ].
+ nBuffer := endIndex - bufferIndex.
+!
+
+readImage
+ "read an image in pcx format from inStream"
inStream binary.
- fileSize := aStream size.
- fileSize < 128 ifTrue:[
+ header := ByteArray uninitializedNew:128.
+ (inStream nextBytes:128 into:header) == 128 ifFalse:[
^ self fileFormatError:'short file'.
].
- header := ByteArray uninitializedNew:128.
- aStream nextBytes:128 into:header.
-
(self class isValidPCXHeader:header) ifFalse:[
^ self fileFormatError:'wrong header'.
].
- img := self fromStreamWithHeader:header.
- ^ img
-
- "Modified: / 3.2.1998 / 17:58:17 / cg"
+ self readRestAfterHeader.
!
-fromStreamWithHeader:header
+readRestAfterHeader
"read an raw image in pcx format from aStream.
The header has already been read into the header argument."
| inDepth version compression nPlanes xmin ymin xmax ymax
- paletteType rawMap rMap gMap bMap
- endIndex "{Class: SmallInteger }"
- srcIndex "{Class: SmallInteger }"
- dstIndex "{Class: SmallInteger }"
- rowIndex "{Class: SmallInteger }"
- h "{Class: SmallInteger }"
- byte "{Class: SmallInteger }"
- nByte "{Class: SmallInteger }"
- srcBytesPerRow "{Class: SmallInteger }"
- value "{Class: SmallInteger }"
- idx2 "{Class: SmallInteger }"
- dataBytes buffer
- bufferIndex "{Class: SmallInteger }"
- bendIndex "{Class: SmallInteger }"
- nBuffer "{Class: SmallInteger }"
- mapSize nMaxPad|
+ paletteType
+ byte "{Class: SmallInteger }"
+ nMaxPad|
"/ typedef struct { /*header for PCX bitmap files*/
"/ unsigned char signature; /*1 PCX file identifier*/
@@ -190,7 +305,7 @@
"/ 'depth=' print. inDepth printNL.
nPlanes := header at:66.
"/ 'planes=' print. nPlanes printNL.
- srcBytesPerRow := header wordAt:67 MSB:false.
+ sourceBytesPerRow := header wordAt:67 MSB:false.
"/ 'srcBytesPerRow=' print. srcBytesPerRow printNL.
paletteType := header at:69.
@@ -216,160 +331,34 @@
"/ 'height=' print. width printNL.
(version == 2) ifTrue:[
- "read the 16-entry colormap"
-
- rawMap := ByteArray uninitializedNew:(16*3).
- rawMap replaceFrom:1 to:(16*3) with:header startingAt:17.
- rMap := ByteArray new:16.
- gMap := ByteArray new:16.
- bMap := ByteArray new:16.
- srcIndex := 1.
- 1 to:16 do:[:i |
- |r g b|
-
- r := rawMap at:srcIndex.
- g := rawMap at:srcIndex+1.
- b := rawMap at:srcIndex+2.
-
- rMap at:i put:r.
- gMap at:i put:g.
- bMap at:i put:b.
- srcIndex := srcIndex + 3.
- ].
+ colorMap := self extractColorMap16.
].
compression == 1 ifTrue:[
- data := dataBytes := ByteArray uninitializedNew:(height * srcBytesPerRow).
-
- buffer := ByteArray uninitializedNew:4096.
- bufferIndex := 1.
- bendIndex := 1.
-
- rowIndex := 1.
- h := height.
- 1 to:h do:[:row |
- dstIndex := rowIndex.
- endIndex := dstIndex + srcBytesPerRow.
- [dstIndex < endIndex] whileTrue:[
- bufferIndex == bendIndex ifTrue:[
- nBuffer := inStream nextBytes:4096 into:buffer.
- bufferIndex := 1.
- bendIndex := nBuffer + 1.
- ].
- byte := buffer at:bufferIndex.
- bufferIndex := bufferIndex + 1.
- ((byte bitAnd:2r11000000) ~~ 2r11000000) ifTrue:[
- dataBytes at:dstIndex put:byte.
- dstIndex := dstIndex + 1.
- ] ifFalse:[
- nByte := byte bitAnd:2r00111111.
- bufferIndex == bendIndex ifTrue:[
- nBuffer := inStream nextBytes:4096 into:buffer.
- bufferIndex := 1.
- bendIndex := nBuffer + 1.
- ].
- value := buffer at:bufferIndex.
- bufferIndex := bufferIndex + 1.
- idx2 := ((dstIndex + nByte) min:endIndex) - 1.
- dataBytes from:dstIndex to:idx2 put:value.
- dstIndex := dstIndex + nByte.
- ].
- ].
- rowIndex := endIndex.
- ].
-
- "/ have to compress - above code reads srcBytesPerRow
- "/ (to keep in sync with RLE); but we want width bytesPerRow
- "/ Can compress in the data-area; leftover pixels are simply ignored
- "/ by other image processing code
- "/
- srcBytesPerRow ~~ width ifTrue:[
- dstIndex := width + 1.
- srcIndex := srcBytesPerRow + 1.
- 2 to:h do:[:row |
- dataBytes replaceFrom:dstIndex to:dstIndex+width-1 with:dataBytes startingAt:srcIndex.
- dstIndex := dstIndex + width.
- srcIndex := srcIndex + srcBytesPerRow
- ]
- ].
- nBuffer := endIndex - bufferIndex.
+ self readCompressedData
] ifFalse:[
- "
- uncompressed; actually untested ...
- "
- data := dataBytes := ByteArray uninitializedNew:(height * width).
- srcBytesPerRow ~~ width ifTrue:[
- dstIndex := 1.
- 1 to:h do:[:row |
- inStream nextBytes:width into:data startingAt:dstIndex.
- dstIndex := dstIndex + width.
- inStream skip:(srcBytesPerRow - width).
- ]
- ] ifFalse:[
- inStream nextBytes:(height * width) into:data.
- ].
- nBuffer := 0.
+ self readUncompressedData
].
(version == 5) ifTrue:[
- "read the 256-entry colormap"
-
- nBuffer ~~ 0 ifTrue:[
- byte := buffer at:bufferIndex.
- bufferIndex := bufferIndex + 1. nBuffer := nBuffer - 1.
- ] ifFalse:[
- byte := inStream next
- ].
-
"/ RLE data is padded - skip over zeros for the 0C-byte
nMaxPad := 15.
+ byte := self nextByteFromBufferOrStream.
+
[(byte ~~ 16r0C) and:[nMaxPad > 0]] whileTrue:[
- nBuffer ~~ 0 ifTrue:[
- byte := buffer at:bufferIndex.
- bufferIndex := bufferIndex + 1. nBuffer := nBuffer - 1.
- ] ifFalse:[
- byte := inStream next
- ].
+ byte := self nextByteFromBufferOrStream.
].
(byte == 16r0C) ifFalse:[
'PCXREADER: no valid 256-entry palette (got' errorPrint.
byte errorPrint. '; expected ' errorPrint. 16rC0 errorPrint. ')' errorPrintCR.
].
- rawMap := ByteArray uninitializedNew:(256*3).
- nBuffer ~~ 0 ifTrue:[
- mapSize := buffer size - bufferIndex + 1.
- mapSize := mapSize min:(256*3).
- rawMap replaceFrom:1 to:mapSize with:buffer startingAt:bufferIndex.
- nBuffer < (256*3) ifTrue:[
- inStream nextBytes:((256*3)-nBuffer) into:rawMap startingAt:nBuffer+1
- ]
- ] ifFalse:[
- inStream nextBytes:(256*3) into:rawMap.
- ].
- rMap := Array new:256.
- gMap := Array new:256.
- bMap := Array new:256.
- srcIndex := 1.
-
- 1 to:256 do:[:i |
- |r g b|
-
- r := rawMap at:srcIndex.
- g := rawMap at:srcIndex+1.
- b := rawMap at:srcIndex+2.
-
- rMap at:i put:r.
- gMap at:i put:g.
- bMap at:i put:b.
- srcIndex := srcIndex + 3.
- ].
+ colorMap := self readColorMap256.
].
photometric := #palette.
samplesPerPixel := 1.
bitsPerSample := #(8).
- colorMap := Colormap redVector:rMap greenVector:gMap blueVector:bMap.
"
|i f|
@@ -378,11 +367,32 @@
"
"Modified: / 3.2.1998 / 17:59:03 / cg"
+!
+
+readUncompressedData
+ |dstIndex|
+
+ "
+ actually untested ...
+ "
+ data := ByteArray uninitializedNew:(height * width).
+ sourceBytesPerRow ~~ width ifTrue:[
+ dstIndex := 1.
+ 1 to:height do:[:row |
+ inStream nextBytes:width into:data startingAt:dstIndex.
+ dstIndex := dstIndex + width.
+ inStream skip:(sourceBytesPerRow - width).
+ ]
+ ] ifFalse:[
+ inStream nextBytes:(height * width) into:data.
+ ].
+ nBuffer := 0.
! !
!PCXReader class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview2/PCXReader.st,v 1.26 2002-03-15 16:52:43 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview2/PCXReader.st,v 1.27 2003-04-04 17:07:54 cg Exp $'
! !
+
PCXReader initialize!
--- a/XPMReader.st Fri Apr 04 19:07:10 2003 +0200
+++ b/XPMReader.st Fri Apr 04 19:07:54 2003 +0200
@@ -13,7 +13,7 @@
"{ Package: 'stx:libview2' }"
ImageReader subclass:#XPMReader
- instanceVariableNames:''
+ instanceVariableNames:'charsPerPixel maskPixelValue characterTranslation'
classVariableNames:''
poolDictionaries:''
category:'Graphics-Images-Support'
@@ -124,7 +124,7 @@
"
XPMReader isValidImageFile:'fooBar'
- XPMReader isValidImageFile:'bitmaps/xpmBitmaps/device_images/ljet.xpm'
+ XPMReader isValidImageFile:'../../goodies/bitmaps/xpmBitmaps/device_images/ljet.xpm'
XPMReader isValidImageFile:'bitmaps/gifImages/garfield.gif'
"
@@ -151,70 +151,24 @@
^ s
!
-fromStream:aStream
- "read an XPM-image from aStream. Return the receiver
- (with all relevant instance variables set for the image)
- or nil on error"
-
- |line
- srcIndex "{ Class: SmallInteger }"
- dstIndex "{ Class: SmallInteger }"
- colorName monoName greyName grey4Name symbolicName colorMapSize redMap greenMap blueMap
- charsPerPixel xlation s bitsPerPixel lineDone maskPixelValue
- state key lastKey lastChar1 lastChar2 c1 c2 lastXLation|
-
- inStream := aStream.
-
- line := aStream nextLine.
- (line notNil and:[line startsWith:'/* XPM']) ifFalse:[
- ^ self fileFormatError:'format error (expected XPM)'.
- ].
-
- line := aStream nextLine.
- [line notNil and:[(line startsWith:'/*') or:[line isBlank or:[(line startsWith:' *')]]]] whileTrue:[
- line := aStream nextLine.
- ].
- (line notNil and:[line startsWith:'static char']) ifFalse:[
- ^ self fileFormatError:'format error (expected static char)'.
- ].
- line := aStream nextLine.
- (line notNil and:[line startsWith:'/*']) ifTrue:[
- [line notNil
- and:[(line startsWith:'/*') or:[line startsWith:' *']]] whileTrue:[
- line := aStream nextLine.
- ].
- ].
- line notNil ifTrue:[
- line := line withoutSeparators
- ].
- (line notNil and:[line startsWith:'"']) ifFalse:[
- ^ self fileFormatError:'format error (expected "ww hh nn mm)'.
- ].
- s := ReadStream on:line.
- s next. "skip quote"
- width := Integer readFrom:s.
- height := Integer readFrom:s.
- colorMapSize := Integer readFrom:s.
- charsPerPixel := Integer readFrom:s.
- charsPerPixel ~~ 1 ifTrue:[
- xlation := Dictionary new:colorMapSize.
- ] ifFalse:[
- xlation := Array new:256.
- ].
+readColorMap:colorMapSize
+ |redMap greenMap blueMap s key lineDone state
+ symbolicName monoName greyName grey4Name colorName|
redMap := ByteArray new:colorMapSize.
greenMap := ByteArray new:colorMapSize.
blueMap := ByteArray new:colorMapSize.
colorMap := Colormap redVector:redMap greenVector:greenMap blueVector:blueMap.
+
1 to:colorMapSize do:[:colorIndex |
|index line color t word|
- line := aStream nextLine.
+ line := inStream nextLine.
[line notNil and:[line startsWith:'/*']] whileTrue:[
[line notNil and:[(line endsWith:'*/') not]] whileTrue:[
- line := aStream nextLine.
+ line := inStream nextLine.
].
- line := aStream nextLine.
+ line := inStream nextLine.
].
line notNil ifTrue:[
line := line withoutSeparators
@@ -227,10 +181,10 @@
s next. "skip quote"
charsPerPixel ~~ 1 ifTrue:[
key := s next:charsPerPixel.
- xlation at:key put:colorIndex - 1.
+ characterTranslation at:key put:colorIndex - 1.
] ifFalse:[
index := s next asciiValue.
- xlation at:index put:colorIndex - 1.
+ characterTranslation at:index put:colorIndex - 1.
].
lineDone := false.
@@ -339,6 +293,58 @@
blueMap at:colorIndex put:(color blue asFloat * 255.0 // 100).
].
].
+!
+
+readImage
+ "read an XPM-image from my inStream. Return the receiver
+ (with all relevant instance variables set for the image)
+ or nil on error"
+
+ |line
+ srcIndex "{ Class: SmallInteger }"
+ dstIndex "{ Class: SmallInteger }"
+ colorMapSize
+ s bitsPerPixel key lastKey lastChar1 lastChar2 c1 c2 lastXLation|
+
+ line := inStream nextLine.
+ (line notNil and:[line startsWith:'/* XPM']) ifFalse:[
+ ^ self fileFormatError:'format error (expected XPM)'.
+ ].
+
+ line := inStream nextLine.
+ [line notNil and:[(line startsWith:'/*') or:[line isBlank or:[(line startsWith:' *')]]]] whileTrue:[
+ line := inStream nextLine.
+ ].
+ (line notNil and:[line startsWith:'static char']) ifFalse:[
+ ^ self fileFormatError:'format error (expected static char)'.
+ ].
+ line := inStream nextLine.
+ (line notNil and:[line startsWith:'/*']) ifTrue:[
+ [line notNil
+ and:[(line startsWith:'/*') or:[line startsWith:' *']]] whileTrue:[
+ line := inStream nextLine.
+ ].
+ ].
+ line notNil ifTrue:[
+ line := line withoutSeparators
+ ].
+ (line notNil and:[line startsWith:'"']) ifFalse:[
+ ^ self fileFormatError:'format error (expected "ww hh nn mm)'.
+ ].
+ s := ReadStream on:line.
+ s next. "skip quote"
+ width := Integer readFrom:s.
+ height := Integer readFrom:s.
+ colorMapSize := Integer readFrom:s.
+ charsPerPixel := Integer readFrom:s.
+
+ charsPerPixel ~~ 1 ifTrue:[
+ characterTranslation := Dictionary new:colorMapSize.
+ ] ifFalse:[
+ characterTranslation := Array new:256.
+ ].
+
+ self readColorMap:colorMapSize.
"actually, could make it an image with less depth most of the time ..."
@@ -355,9 +361,9 @@
dstIndex := 1.
1 to:height do:[:row |
- line := aStream nextLine withoutSpaces.
+ line := inStream nextLine withoutSpaces.
[line notNil and:[line startsWith:'/*']] whileTrue:[
- line := aStream nextLine withoutSpaces.
+ line := inStream nextLine withoutSpaces.
].
line notNil ifTrue:[
line := line withoutSeparators
@@ -370,7 +376,7 @@
1 to:width do:[:col |
key := line at:srcIndex.
key ~~ lastKey ifTrue:[
- lastXLation := xlation at:key asciiValue.
+ lastXLation := characterTranslation at:key asciiValue.
lastKey := key
].
data at:dstIndex put:lastXLation.
@@ -390,7 +396,7 @@
(c1 ~~ lastChar1 or:[c2 ~~ lastChar2]) ifTrue:[
key at:1 put:c1.
key at:2 put:c2.
- lastXLation := xlation at:key.
+ lastXLation := characterTranslation at:key.
lastChar1 := c1.
lastChar2 := c2.
].
@@ -410,9 +416,9 @@
s next. "/ skip dquote
1 to:width do:[:col |
key := s next:charsPerPixel.
-"/ data at:dstIndex put:(xlation at:key).
+"/ data at:dstIndex put:(characterTranslation at:key).
key ~= lastKey ifTrue:[
- lastXLation := xlation at:key.
+ lastXLation := characterTranslation at:key.
lastKey := key
].
data at:dstIndex put:lastXLation.
@@ -437,10 +443,7 @@
].
"
- XPMReader fromStream:('bitmaps/ljet.xpm' asFilename readStream)
- XPMReader fromStream:('bitmaps/magtape.xpm' asFilename readStream)
- XPMReader fromStream:('bitmaps/pixmap.xpm' asFilename readStream)
- XPMReader fromStream:('bitmaps/SBrowser.xbm' asFilename readStream)
+ XPMReader fromStream:('../../goodies/bitmaps/xpmBitmaps/FATAL.xpm' asFilename readStream)
"
"Created: / 24.9.1995 / 06:20:06 / claus"
@@ -573,7 +576,7 @@
!XPMReader class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview2/XPMReader.st,v 1.49 2003-03-02 18:39:45 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libview2/XPMReader.st,v 1.50 2003-04-04 17:07:22 cg Exp $'
! !
XPMReader initialize!