--- a/PCXReader.st Mon Aug 28 13:34:44 2017 +0200
+++ b/PCXReader.st Mon Aug 28 19:31:18 2017 +0200
@@ -41,6 +41,9 @@
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;
+ if at all, use it to convert old image files to newer formats,
+ such as png, tiff or jpg.
Due to not having too many examples for testing,
this could fail to read some files.
@@ -162,8 +165,8 @@
!
readCompressedData
- |bendIndex rowIndex dstIndex endIndex byte nByte value idx2
- srcIndex bytesPerPane planeData imageBytesPerRow|
+ |bendIndex rowStartIndex endIndex byte nByte value idx2
+ srcIndex dstIndex srcRowStartIndex dstRowStartIndex bytesPerPane planeData imageBytesPerRow|
imageBytesPerRow := (((width * depth) + 7) // 8).
@@ -175,15 +178,14 @@
bufferIndex := 1.
bendIndex := 1.
-
- rowIndex := 1.
+ rowStartIndex := 1.
1 to:height do:[:row |
1 to:nPlanes do:[:planeNr |
- |dst|
+ |planeBytes|
- dst := planeData at:planeNr.
+ planeBytes := planeData at:planeNr.
- dstIndex := rowIndex.
+ dstIndex := rowStartIndex.
endIndex := dstIndex + sourceBytesPerRow.
[dstIndex < endIndex] whileTrue:[
@@ -195,7 +197,7 @@
byte := buffer at:bufferIndex.
bufferIndex := bufferIndex + 1.
((byte bitAnd:2r11000000) ~~ 2r11000000) ifTrue:[
- dst at:dstIndex put:byte.
+ planeBytes at:dstIndex put:byte.
dstIndex := dstIndex + 1.
] ifFalse:[
nByte := byte bitAnd:2r00111111.
@@ -207,37 +209,89 @@
value := buffer at:bufferIndex.
bufferIndex := bufferIndex + 1.
idx2 := ((dstIndex + nByte) min:endIndex) - 1.
- dst from:dstIndex to:idx2 put:value.
+ planeBytes from:dstIndex to:idx2 put:value.
dstIndex := dstIndex + nByte.
].
].
].
- "/ rowIndex := rowIndex + endIndex.
- rowIndex := rowIndex + imageBytesPerRow. "/endIndex.
+ "/ rowStartIndex := endIndex.
+ rowStartIndex := rowStartIndex + imageBytesPerRow.
].
nBuffer := endIndex - bufferIndex.
"/ now merge the planes
nPlanes > 1 ifTrue:[
depth == 8 ifTrue:[
- (nPlanes == 3 or:[nPlanes == 4]) ifTrue:[
+ (nPlanes >= 3) ifTrue:[
"/ a simple rgb image
+ nPlanes := nPlanes min:4.
+
data := ByteArray uninitializedNew:(nPlanes*width*height).
+ srcRowStartIndex := dstRowStartIndex := 1.
+ 1 to:height do:[:y |
+ 1 to:nPlanes do:[:p |
+ |planeBytes|
+
+ dstIndex := dstRowStartIndex + (p - 1).
+ srcIndex := srcRowStartIndex.
+ planeBytes := planeData at:p.
+ 1 to:width do:[:x |
+ data at:dstIndex put:(planeBytes at:srcIndex).
+ dstIndex := dstIndex + nPlanes.
+ srcIndex := srcIndex + 1.
+ ].
+ ].
+ srcRowStartIndex := srcRowStartIndex + imageBytesPerRow.
+ dstRowStartIndex := dstRowStartIndex + (width * nPlanes).
+ ].
+ ].
+ depth := nPlanes * 8.
+ photometric := nPlanes==3 ifTrue:[#rgb] ifFalse:[#rgba].
+ ] ifFalse:[
+ (depth == 1) ifTrue:[
+ |newDepth nPlanesUsed|
+
+ nPlanesUsed := nPlanes min:4.
+ newDepth := (nPlanesUsed * depth) nextPowerOf2.
+
+ data := ByteArray new:((width*height*newDepth)+7)//8.
srcIndex := dstIndex := 1.
1 to:height do:[:y |
+ |inMask outBitCount outBits|
+
+ inMask := 16r80.
+ outBitCount := 0.
+ outBits := 0.
1 to:width do:[:x |
- 1 to:nPlanes do:[:p |
- data at:dstIndex put:((planeData at:p) at:srcIndex).
+ 1 to:nPlanesUsed do:[:p |
+ outBits := (outBits bitShift:1).
+ (((planeData at:p) at:srcIndex) bitAnd:inMask) ~~ 0 ifTrue:[
+ outBits := outBits bitOr:1.
+ ].
+ ].
+ outBits := outBits bitShift:(newDepth-nPlanesUsed).
+ outBitCount := outBitCount + newDepth.
+
+ outBitCount >= 8 ifTrue:[
+ data at:dstIndex put:((data at:dstIndex) bitOr:outBits).
dstIndex := dstIndex + 1.
- ].
- srcIndex := srcIndex + 1.
+ outBitCount := 0.
+ outBits := 0.
+ ].
+ inMask := inMask rightShift:1.
+ inMask == 0 ifTrue:[
+ inMask := 16r80.
+ srcIndex := srcIndex + 1.
+ ].
].
].
+ depth := newDepth.
+ "/ rgbi colormap.
+self halt.
+
+ ] ifFalse:[
+ self halt.
].
- depth := nPlanes * depth.
- photometric := #rgb.
- ] ifFalse:[
- self halt.
].
].
@@ -262,7 +316,7 @@
"/ ].
"/ ].
- "Modified: / 28-08-2017 / 13:28:56 / cg"
+ "Modified (format): / 28-08-2017 / 18:01:46 / cg"
!
readRestAfterHeader
@@ -356,6 +410,22 @@
self readUncompressedData
].
+ "/ warning: depth might be changed by readCompressedData
+ depth == 24 ifTrue:[
+ samplesPerPixel := 3.
+ bitsPerSample := #( 8 8 8 ).
+ photometric := #rgb.
+ ] ifFalse:[
+ depth == 32 ifTrue:[
+ samplesPerPixel := 4.
+ bitsPerSample := #( 8 8 8 8).
+ photometric := #rgba.
+ ] ifFalse:[
+ samplesPerPixel := 1.
+ bitsPerSample := { depth }.
+ ].
+ ].
+
photometric == #palette ifTrue:[
(version == 5) ifTrue:[
true "depth == 8" ifTrue:[
@@ -388,21 +458,13 @@
].
].
- depth == 24 ifTrue:[
- samplesPerPixel := 3.
- bitsPerSample := #( 8 8 8 ).
- ] ifFalse:[
- samplesPerPixel := 1.
- bitsPerSample := { depth }.
- ].
-
"
|i f|
i := Image fromFile:'somefile.pcx'.
i inspect.
"
- "Modified: / 28-08-2017 / 13:30:58 / cg"
+ "Modified: / 28-08-2017 / 15:53:11 / cg"
!
readUncompressedData