#UI_ENHANCEMENT
authorClaus Gittinger <cg@exept.de>
Thu, 24 Mar 2016 18:31:08 +0100
changeset 3607 a1b3d6654923
parent 3605 a0893b077a00
child 3608 ffd67647a98b
#UI_ENHANCEMENT class: PNGReader class definition comment/format in: #paethPredictLeft:above:aboveLeft: #save:onStream: changed: #filterPaeth: #getIHDRChunk #setColorType: tuning
PNGReader.st
--- a/PNGReader.st	Thu Mar 24 05:03:41 2016 +0000
+++ b/PNGReader.st	Thu Mar 24 18:31:08 2016 +0100
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
 "
  COPYRIGHT (c) 1996 by Claus Gittinger
               All Rights Reserved
@@ -16,9 +14,9 @@
 "{ NameSpace: Smalltalk }"
 
 ImageReader subclass:#PNGReader
-	instanceVariableNames:'colorType bitsPerChannel depth compressionMethod filterMethod
-		interlaceMode bytesPerScanline globalDataChunk thisScanline
-		prevScanline'
+	instanceVariableNames:'colorType bitsPerChannel bitsPerPixel depth compressionMethod
+		filterMethod interlaceMode bytesPerScanline globalDataChunk
+		thisScanline prevScanline'
 	classVariableNames:'Verbose'
 	poolDictionaries:''
 	category:'Graphics-Images-Readers'
@@ -482,7 +480,49 @@
     
     |delta|
 
-    delta := self bitsPerPixel // 8 max:1.
+%{
+    if (__isByteArray(__INST(thisScanline))
+     && __isByteArray(__INST(prevScanline))
+     && __isSmallInteger(__INST(depth))
+     && __isSmallInteger(count)) {
+        unsigned char *__thisScanline = __byteArrayVal(__INST(thisScanline));
+        unsigned int __sz_this = __byteArraySize(__INST(thisScanline));
+        unsigned char *__prevScanline = __byteArrayVal(__INST(prevScanline));
+        unsigned int __sz_prev = __byteArraySize(__INST(prevScanline));
+        INT __count = __intVal(count);
+        INT __delta = __intVal(__INST(depth)) / 8;
+        int __i;
+        
+        if (__delta < 1) __delta = 1;
+        for (__i=0; __i<__delta; __i++) {
+            unsigned int __pix = __thisScanline[__i] + __prevScanline[__i];
+            __thisScanline[__i] = __pix;
+        }
+        for (; __i < __count; __i++) {
+            int __pCenter = __thisScanline[__i];
+            int __pLeft = __thisScanline[__i - __delta];
+            int __pAbove = __prevScanline[__i];
+            int __pAboveLeft = __prevScanline[__i - __delta];
+            int __pa, __pb, __pc;
+            int __p;
+            
+            __pa = (__pAbove - __pAboveLeft); 
+            __pa = __pa < 0 ? -__pa : __pa;
+            __pb = (__pLeft - __pAboveLeft);
+            __pb = __pb < 0 ? -__pb : __pb;
+            __pc = __pLeft + __pAbove - __pAboveLeft - __pAboveLeft;
+            __pc = __pc < 0 ? -__pc : __pc; 
+            if ((__pa <= __pb) && (__pa <= __pc)) __p = __pLeft;
+            else if (__pb <= __pc) __p = __pAbove;
+            else __p = __pAboveLeft;
+            
+            __thisScanline[__i] = __pCenter + __p;
+        }
+        RETURN(self);
+    }
+%}.
+
+    delta := depth // 8 max:1.
     1 to:delta do:[:i | 
         thisScanline 
             at:i
@@ -521,20 +561,20 @@
     "Modified: / 03-05-2011 / 12:14:34 / cg"
 !
 
-paethPredictLeft: a above: b aboveLeft: c
+paethPredictLeft: l above: a aboveLeft: al
     "Predicts the value of a pixel based on nearby pixels, based on Paeth (GG II, 1991)"
 
     | pa pb pc |
 
-    pa := b > c ifTrue: [b - c] ifFalse: [c - b].
-    pb := a > c ifTrue: [a - c] ifFalse: [c - a].
-    pc := a + b - c - c.
+    pa := a > al ifTrue: [a - al] ifFalse: [al - a].
+    pb := l > al ifTrue: [l - al] ifFalse: [al - l].
+    pc := l + a - al - al.
     pc < 0 ifTrue: [
         pc := pc * -1
     ].
-    ((pa <= pb) and: [pa <= pc]) ifTrue: [^ a].
-    (pb <= pc) ifTrue: [^ b].
-    ^ c
+    ((pa <= pb) and: [pa <= pc]) ifTrue: [^ l].
+    (pb <= pc) ifTrue: [^ a].
+    ^ al
 ! !
 
 !PNGReader methodsFor:'private-pixel copy'!
@@ -761,7 +801,8 @@
     ].
     self reportDimension.
 
-    depth := inStream nextByte.            "/ bits-per-channel
+    bitsPerChannel := inStream nextByte.
+    depth := bitsPerChannel. "/ will be changed by setColorType.
     colorType := inStream nextByte.
 
     compressionMethod := inStream nextByte.
@@ -772,7 +813,7 @@
         'PNGReader: IHDR:' infoPrintCR.
         'PNGReader:   width: ' infoPrint. width infoPrintCR.
         'PNGReader:   height: ' infoPrint. height infoPrintCR.
-        'PNGReader:   depth: ' infoPrint. depth infoPrintCR.
+        'PNGReader:   bitsPerChannel: ' infoPrint. bitsPerChannel infoPrintCR.
         'PNGReader:   colorType: ' infoPrint. colorType infoPrintCR.
         'PNGReader:   compressionMethod: ' infoPrint. compressionMethod infoPrintCR.
         'PNGReader:   filterMethod: ' infoPrint. filterMethod infoPrintCR.
@@ -789,51 +830,56 @@
     colorType == 0 ifTrue:[
         photometric := #blackIs0.
         samplesPerPixel := 1.
-        bitsPerSample := Array with:depth.
+        bitsPerSample := Array with:bitsPerChannel.
+        depth := bitsPerChannel.
         ^ true.
     ].
 
     colorType == 2 ifTrue:[
-        depth < 8 ifTrue:[
+        bitsPerChannel < 8 ifTrue:[
             'PNGReader: invalid colorType/depth combination' infoPrintCR.
             ^ false.
         ].
         photometric := #rgb.
         samplesPerPixel := 3.
-        bitsPerSample := Array with:depth with:depth with:depth.
+        bitsPerSample := Array with:bitsPerChannel with:bitsPerChannel with:bitsPerChannel.
+        depth := bitsPerChannel * 3.
         ^ true.
     ].
 
     colorType == 3 ifTrue:[
-        depth == 16 ifTrue:[
+        bitsPerChannel == 16 ifTrue:[
             'PNGReader: invalid colorType/depth combination' infoPrintCR.
             ^ false.
         ].
         photometric := #palette.
         samplesPerPixel := 1.
-        bitsPerSample := Array with:depth.
+        bitsPerSample := Array with:bitsPerChannel.
+        depth := bitsPerChannel.
         ^ true.
     ].
 
     colorType == 4 ifTrue:[
-        depth < 8 ifTrue:[
+        bitsPerChannel < 8 ifTrue:[
             'PNGReader: invalid colorType/depth combination' infoPrintCR.
             ^ false.
         ].
         photometric := #blackIs0.
         samplesPerPixel := 2.
-        bitsPerSample := Array with:depth with:depth.
+        bitsPerSample := Array with:bitsPerChannel with:bitsPerChannel.
+        depth := bitsPerChannel * 2.
         ^ true.
     ].
 
     colorType == 6 ifTrue:[
-        depth < 8 ifTrue:[
+        bitsPerChannel < 8 ifTrue:[
             'PNGReader: invalid colorType/depth combination' infoPrintCR.
             ^ false.
         ].
         photometric := #rgb.
         samplesPerPixel := 4.
-        bitsPerSample := Array with:depth with:depth with:depth with:depth.
+        bitsPerSample := Array with:bitsPerChannel with:bitsPerChannel with:bitsPerChannel with:bitsPerChannel.
+        depth := bitsPerChannel * 4.
         ^ true.
     ].