PNGReader.st
changeset 1671 6fbb20a4af3a
parent 647 6f26c76aa0c9
child 1694 3a77d9b69cf7
--- a/PNGReader.st	Fri Nov 15 12:26:54 2002 +0100
+++ b/PNGReader.st	Fri Nov 15 22:13:43 2002 +0100
@@ -12,6 +12,8 @@
 
 
 
+"{ Package: 'stx:libview2' }"
+
 ImageReader subclass:#PNGReader
 	instanceVariableNames:'colorType depth compressionMethod filterMethod interlaceMode
 		redBytes greenBytes blueBytes'
@@ -105,8 +107,7 @@
 
     (self processChunk:type len:len) ifFalse:[^ false].
 
-    inStream skip:4.
-"/    crc := inStream nextLongMSB:true.
+    crc := inStream nextLongMSB:true.  "/ ignored - for now
     ^ true
 
     "Created: 21.6.1996 / 21:09:36 / cg"
@@ -163,6 +164,10 @@
     type = 'zTXt' ifTrue:[^ self processZTXTChunkLen:len].
     type = 'PLTE' ifTrue:[^ self processPLTEChunkLen:len].
 
+    type = 'pHYs' ifTrue:[^ self processPHYSChunkLen:len].
+    type = 'tRNS' ifTrue:[^ self processTRNSChunkLen:len].
+    type = 'IHDR' ifTrue:[^ self processIHDRChunkLen:len].
+
     ('PNGReader: unrecognized chunk: ' , type , ' ignored.') infoPrintCR.
 
     inStream skip:len.
@@ -180,13 +185,77 @@
 !
 
 processIDATChunkLen:len
+    interlaceMode == 0 ifTrue: [
+        ^ self processNonInterlacedDATA:len
+    ]. 
+    ^ self processInterlacedDATA:len
+!
+
+processIHDRChunkLen:len
+    "header chunk - currently unhandled"
+
+    |width height bitsPerChannel interlaceMethod palette image bitsPerPixel bytesPerScanline rowSize|
+
+self halt.        
+    width := inStream nextLongMSB:true.   "/ 1..4
+    height := inStream nextLongMSB:true.  "/ 5..8
+    bitsPerChannel := inStream nextByte.  "/ 9
+    colorType := inStream nextByte.       "/ 10
+    inStream nextByte. "/ 11
+    inStream nextByte. "/ 12
+    interlaceMethod := inStream nextByte. "/ 13
+
+    (#(2 4 6) includes: colorType) ifTrue:[
+        depth := 32.
+        palette := self class defaultPalette.
+        image := Image extent: width @ height depth: depth palette: palette
+    ].
+    (#(0 3) includes: colorType) ifTrue:[ 
+        depth := bitsPerChannel min: 8.
+        image := Image extent: width @ height
+                       depth: depth
+                       palette: (colorType = 0 
+                                        ifTrue: [self grayColorsFor: depth] 
+                                        ifFalse: [palette := self class defaultPalette])].
+    bitsPerPixel := (BPP at: colorType + 1) at: bitsPerChannel highBit.
+    bytesPerScanline := (width * bitsPerPixel + 7) // 8.
+    rowSize := image width * image depth + 31 >> 5
+!
+
+processInterlacedDATA:len
     inStream skip:len.
     ^ true
+!
 
-    "Created: 21.6.1996 / 21:15:35 / cg"
+processNonInterlacedDATA:len
+    | zlibReader filter temp prevScanline thisScanline bytesPerScanline filtersSeen|
+
+    zlibReader := Net.ZLibReadStream on:inStream from: 1 to:len.
+    prevScanline := ByteArray new: bytesPerScanline.
+    thisScanline := ByteArray new: bytesPerScanline.
+    0 to: height - 1 do: 
+            [:index | 
+            filter := (zlibReader next: 1) first.
+            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.
+            temp := prevScanline.
+            prevScanline := thisScanline.
+            thisScanline := temp]
+!
+
+processPHYSChunkLen:len
+    "physical pixel chunk - currently unhandled"
+
+    'PNGReader: unhandled chunk type: PHYS' infoPrintCR.
+    ^ false
 !
 
 processPLTEChunkLen:len
+    "read a color palette"
+
     |n "{ Class: SmallInteger }"|
 
     (len \\ 3) ~~ 0 ifTrue:[
@@ -250,7 +319,7 @@
     inStream := aStream.
     aStream binary.
 
-    "GIF-files are always msb (network-world)"
+    "PNG-files are always msb (network-world)"
     byteOrder := #msb.
 
     header := ByteArray new:8.
@@ -277,49 +346,11 @@
         'PNGReader: invalid interlaceMode' infoPrintCR.
         ^ nil.
     ].
-
-    colorType == 0 ifTrue:[
-        photometric := #blackIs0.
-        samplesPerPixel := 1.
-        bitsPerSample := Array with:depth.
-    ] ifFalse:[ colorType == 2 ifTrue:[
-        depth < 8 ifTrue:[
-            'PNGReader: invalid colorType/depth combination' infoPrintCR.
-            ^ nil.
-        ].
-        photometric := #rgb.
-        samplesPerPixel := 3.
-        bitsPerSample := Array with:depth with:depth with:depth.
-    ] ifFalse:[ colorType == 3 ifTrue:[
-        depth == 16 ifTrue:[
-            'PNGReader: invalid colorType/depth combination' infoPrintCR.
-            ^ nil.
-        ].
-        photometric := #palette.
-        samplesPerPixel := 1.
-        bitsPerSample := Array with:depth.
-    ] ifFalse:[ colorType == 4 ifTrue:[
-        depth < 8 ifTrue:[
-            'PNGReader: invalid colorType/depth combination' infoPrintCR.
-            ^ nil.
-        ].
-        photometric := #blackIs0.
-        samplesPerPixel := 2.
-        bitsPerSample := Array with:depth with:depth.
-    ] ifFalse:[ colorType == 6 ifTrue:[
-        depth < 8 ifTrue:[
-            'PNGReader: invalid colorType/depth combination' infoPrintCR.
-            ^ nil.
-        ].
-        photometric := #rgb.
-        samplesPerPixel := 4.
-        bitsPerSample := Array with:depth with:depth with:depth with:depth.
-    ] ifFalse:[
-        ('PNGReader: invalid colorType: ' , colorType printString , '.') infoPrintCR.
+    (self setColorType:colorType) ifFalse:[
         ^ nil
-    ]]]]].
+    ].
         
-    [self getChunk] whileTrue:[ ].
+    [self getChunk] whileTrue.
 
     photometric == #palette ifTrue:[
         redBytes isNil ifTrue:[
@@ -339,11 +370,68 @@
     "
 
     "Modified: 21.6.1996 / 21:44:34 / cg"
+!
+
+setColorType:colorType
+    colorType == 0 ifTrue:[
+        photometric := #blackIs0.
+        samplesPerPixel := 1.
+        bitsPerSample := Array with:depth.
+        ^ true.
+    ].
+
+    colorType == 2 ifTrue:[
+        depth < 8 ifTrue:[
+            'PNGReader: invalid colorType/depth combination' infoPrintCR.
+            ^ false.
+        ].
+        photometric := #rgb.
+        samplesPerPixel := 3.
+        bitsPerSample := Array with:depth with:depth with:depth.
+        ^ true.
+    ].
+
+    colorType == 3 ifTrue:[
+        depth == 16 ifTrue:[
+            'PNGReader: invalid colorType/depth combination' infoPrintCR.
+            ^ false.
+        ].
+        photometric := #palette.
+        samplesPerPixel := 1.
+        bitsPerSample := Array with:depth.
+        ^ true.
+    ].
+
+    colorType == 4 ifTrue:[
+        depth < 8 ifTrue:[
+            'PNGReader: invalid colorType/depth combination' infoPrintCR.
+            ^ false.
+        ].
+        photometric := #blackIs0.
+        samplesPerPixel := 2.
+        bitsPerSample := Array with:depth with:depth.
+        ^ true.
+    ].
+
+    colorType == 6 ifTrue:[
+        depth < 8 ifTrue:[
+            'PNGReader: invalid colorType/depth combination' infoPrintCR.
+            ^ false.
+        ].
+        photometric := #rgb.
+        samplesPerPixel := 4.
+        bitsPerSample := Array with:depth with:depth with:depth with:depth.
+        ^ true.
+    ].
+
+    ('PNGReader: invalid colorType: ' , colorType printString , '.') infoPrintCR.
+    ^ false
 ! !
 
 !PNGReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/PNGReader.st,v 1.3 1997-06-30 20:56:07 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/PNGReader.st,v 1.4 2002-11-15 21:13:43 cg Exp $'
 ! !
+
 PNGReader initialize!