PCXReader.st
changeset 1737 a1ed08195ee7
parent 1562 3b444efb61ee
child 1745 4fa0fad2a463
--- 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!