PNGReader.st
changeset 2696 99339f07db68
parent 2695 6197b6af7f4f
child 2697 8e8223bf25af
--- a/PNGReader.st	Fri Jul 31 12:58:11 2009 +0200
+++ b/PNGReader.st	Fri Jul 31 14:14:55 2009 +0200
@@ -13,7 +13,8 @@
 
 ImageReader subclass:#PNGReader
 	instanceVariableNames:'colorType depth compressionMethod filterMethod interlaceMode
-		redBytes greenBytes blueBytes bytesPerScanline globalDataChunk'
+		redBytes greenBytes blueBytes bytesPerScanline globalDataChunk
+		thisScanline prevScanline'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Graphics-Images-Readers'
@@ -104,7 +105,7 @@
     "Modified: 21.6.1996 / 20:38:46 / cg"
 ! !
 
-!PNGReader methodsFor:'private'!
+!PNGReader methodsFor:'private-chunks'!
 
 processBKGDChunkLen:len
     inStream skip:len.
@@ -229,24 +230,30 @@
 !
 
 processNonInterlacedGlobalDATA
-    | data n zlibReader filter temp prevScanline thisScanline bytesPerScanline filtersSeen|
+    | "data n" zlibReader filter temp bytesPerScanline "filtersSeen" copyMethod|
+
+    "/ filtersSeen := Set new.
 
 "/    data := ByteArray new:(self bytesPerRow * height)+1000.
 "/    n := ZipStream uncompress: globalDataChunk into: data.
 "/    self halt.
 
-    zlibReader := ZipStream readOpenAsZipStreamOn:(globalDataChunk readStream). 
+    zlibReader := ZipStream readOpenAsZipStreamOn:(globalDataChunk readStream).
+    zlibReader binary.
     bytesPerScanline := self bytesPerRow.
 
+    copyMethod := #(copyPixelsGray: nil copyPixelsRGB: copyPixelsIndexed:
+                    copyPixelsGrayAlpha: nil copyPixelsRGBA:) at:colorType+1.     
+
     prevScanline := ByteArray new: bytesPerScanline.
     thisScanline := ByteArray new: bytesPerScanline.
     0 to: height - 1 do:[:index | 
         filter := (zlibReader next: 1) first.
-        filtersSeen add: filter.
+        "/ filtersSeen add: filter.
         (filter isNil or: [(filter between: 0 and: 4) not]) ifTrue: [^self].
-        thisScanline := zlibReader next: bytesPerScanline into: thisScanline startingAt: 1.
-        self filterScanline: filter count: bytesPerScanline.
-        self copyPixels: index.
+        zlibReader next: bytesPerScanline into: thisScanline startingAt: 1.
+        filter ~~ 0 ifTrue:[ self filterScanline: filter count: bytesPerScanline ].
+        self perform:copyMethod with: index.
         temp := prevScanline.
         prevScanline := thisScanline.
         thisScanline := temp
@@ -315,6 +322,26 @@
     "Created: 21.6.1996 / 21:15:58 / cg"
 ! !
 
+!PNGReader methodsFor:'private-filtering'!
+
+filterHorizontal:count
+    "use the pixel to the left as a predictor"
+
+    |delta|
+
+    delta := self bitsPerPixel // 8 max:1.
+    delta+1 to:count do:[:i|
+        thisScanline at:i put:(((thisScanline at:i)+ (thisScanline at:i-delta)) bitAnd:255) 
+    ]
+!
+
+filterScanline:filterType count:count
+    self 
+        perform:(#(filterNone: filterHorizontal: filterVertical: filterAverage: filterPaeth:)
+                    at:filterType+1)
+        with:count
+! !
+
 !PNGReader methodsFor:'private-reading'!
 
 getChunk
@@ -576,7 +603,7 @@
 !PNGReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/PNGReader.st,v 1.13 2009-07-31 10:58:11 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/PNGReader.st,v 1.14 2009-07-31 12:14:55 cg Exp $'
 ! !
 
 PNGReader initialize!