#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Tue, 29 Aug 2017 13:08:29 +0200
changeset 3996 9f8c87c19905
parent 3995 ab4741a8e8f5
child 3997 f388b337715a
#FEATURE by cg class: PCXReader can now read all test images!
PCXReader.st
--- a/PCXReader.st	Tue Aug 29 12:38:15 2017 +0200
+++ b/PCXReader.st	Tue Aug 29 13:08:29 2017 +0200
@@ -40,6 +40,7 @@
 documentation
 "
     this class provides methods to load PCX bitmap files.
+    
     PCX used to be a popular image format in the early PC times,
     but became almost obsolete in the meantime.
     This reader is not tuned and performs slow on non-8bit images;
@@ -50,14 +51,16 @@
     this could fail to read some files. 
     (especially, I have no uncompressed files for testing).
 
-    Only 1,2,4,8 and 24-bit PCX images are supported.
+    1,2,4,8 and 24-bit PCX images are supported, both in single and separate
+    plane formats.
+
     Image writing is not.
 
     [See also:]
         Image Form Icon
         BlitImageReader FaceReader GIFReader JPEGReader PBMReader 
         ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader 
-        XBMReader XPMReader XWDReader 
+        XBMReader XPMReader XWDReader PNGReader JPEGReader
 "
 !
 
@@ -464,7 +467,6 @@
             photometric := #palette.
         ].
     ].
-    self readImageData.
 
     depth == 24 ifTrue:[
         samplesPerPixel := 3.
@@ -481,6 +483,8 @@
         ].
     ].
 
+    self readImageData.
+
     photometric == #palette ifTrue:[ 
        (version == 5) ifTrue:[
             true "depth == 8" ifTrue:[
@@ -520,7 +524,7 @@
      i inspect.
     "
 
-    "Modified: / 29-08-2017 / 12:24:11 / cg"
+    "Modified: / 29-08-2017 / 13:00:56 / cg"
 !
 
 readScanlineTo:data startingAt:startIndex
@@ -582,9 +586,13 @@
             ].
         ] ifFalse:[
             "/ need some bit-stuffing to merge planes...
+            "/ the following code is a q&d, straight forward, and
+            "/ completely untuned hack.
+            
             depth <= 8 ifTrue:[
                 "/ merge into bytes
-                |m0 srcByteIndex inShift mask outBitCount pixelBits outShift xOffs bits|
+                |m0 srcByteIndex inShift mask outBitCount 
+                 pixelBits outShift xOffs bits rowOffsets|
 
                 m0 := #( 16r80 16rC0 nil 16rF0 ) at:bitsPerPixelIn.
                 mask := #( 1 3 0 7 ) at:bitsPerPixelIn.
@@ -595,17 +603,20 @@
                 inShift := 8-bitsPerPixelIn.
                 outShift := 8-(depth).
 
+                rowOffsets := { 0 . sourceBytesPerRow . (sourceBytesPerRow*2) . (sourceBytesPerRow*3) }.
+                rowOffsets := (rowOffsets copyTo:nPlanesUsed) reversed.
+
                 1 to:width do:[:x |
                     "/ collect pixel's bits from planes
                     pixelBits := 0.
-                    rowOffset := 0.
+                    "/ rowOffset := 0.
                     1 to:nPlanesUsed do:[:p |
-                        byte := rowBytes at:xOffs+rowOffset.
+                        byte := rowBytes at:xOffs+(rowOffsets at:p).
                         bits := (byte rightShift:inShift) bitAnd:mask.
                         "/ bits now contains the plane's bits in the low bit positions
                         pixelBits := (pixelBits bitShift:bitsPerPixelIn) bitOr:bits.
 
-                        rowOffset := rowOffset + sourceBytesPerRow.
+                        "/ rowOffset := rowOffset + sourceBytesPerRow.
                     ].
                     inShift := inShift - bitsPerPixelIn.
                     inShift < 0 ifTrue:[
@@ -625,14 +636,16 @@
                         outShift := 8-(depth).
                         dstIndex := dstIndex + 1.
                     ].    
-                ]
+                ].
             ] ifFalse:[
                 depth == 16 ifTrue:[
                     "/ merge into 16bit ints
+                    "/ in theory, this is possible (eg. bitsPerPixel=4; nPlanes=3), 
+                    "/ but I never saw such a file in the wild...
                     self halt.
                 ] ifFalse:[
-                    self error.
                 ]. 
+                self fileFormatError:('unsupported: depth%1 with %2 planes' bindWith:bitsPerPixelIn with:nPlanes).
             ].    
         ].    
     ] ifFalse:[
@@ -640,7 +653,7 @@
     ].
 
     "Created: / 29-08-2017 / 09:49:41 / cg"
-    "Modified: / 29-08-2017 / 12:27:12 / cg"
+    "Modified: / 29-08-2017 / 13:08:03 / cg"
 ! !
 
 !PCXReader methodsFor:'reading'!