--- a/PNGReader.st Thu Mar 24 07:06:00 2016 +0100
+++ b/PNGReader.st Sat Mar 26 08:00:39 2016 +0000
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1996 by Claus Gittinger
All Rights Reserved
@@ -253,8 +251,17 @@
processInterlacedGlobalDATA
"adam7 interlace method"
- | zlibReader filter bytesPerPass startingCol colIncrement rowIncrement
- startingRow cx sc temp "filtersSeen" bitsPerPixel cy|
+ | zlibReader filter
+ bytesPerPass startingCol colIncrement rowIncrement
+ startingRow
+ temp "filtersSeen"
+ cx "{ Class: SmallInteger }"
+ sc "{ Class: SmallInteger }"
+ cy "{ Class: SmallInteger }"
+ startRow "{ Class: SmallInteger }"
+ w "{ Class: SmallInteger }"
+ h "{ Class: SmallInteger }"
+ |
interlaceMode == 1 ifFalse: [
self error:'unsupported interlaced mode'.
@@ -270,17 +277,19 @@
zlibReader := ZipStream readOpenAsZipStreamOn:(globalDataChunk readStream) suppressHeaderAndChecksum:false.
zlibReader binary.
- bitsPerPixel := self bitsPerPixel.
+ h := height.
+ w := width.
1 to: 7 do: [:pass |
(self doPass: pass) ifTrue:[
cx := colIncrement at: pass.
sc := startingCol at: pass.
cy := rowIncrement at: pass.
- bytesPerPass := (((width - sc + cx - 1) // cx * bitsPerPixel) + 7) // 8.
+ bytesPerPass := (((w - sc + cx - 1) // cx * depth) + 7) // 8.
prevScanline := ByteArray new: bytesPerPass.
thisScanline := ByteArray new: bytesPerScanline.
- (startingRow at: pass) to: height - 1 by: cy do: [:y |
+ startRow := startingRow at: pass.
+ startRow to: h-1 by: cy do: [:y |
filter := zlibReader nextByte.
"/ filtersSeen add: filter.
(filter isNil or: [(filter between: 0 and: 4) not])
@@ -470,7 +479,31 @@
|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++) {
+ __thisScanline[__i] += (__prevScanline[__i] >> 1);
+ }
+ for (; __i < __count; __i++) {
+ __thisScanline[__i] += ((__prevScanline[__i] + __thisScanline[__i-__delta]) >> 1);
+ }
+ RETURN(self);
+ }
+%}.
+
+ delta := depth // 8 max:1.
1 to:delta do:[:i |
thisScanline at:i put:((thisScanline at:i) + ((prevScanline at:i) // 2) bitAnd:255)
].
@@ -486,7 +519,28 @@
|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 = __delta; __i < __count; __i++) {
+ __thisScanline[__i] = __thisScanline[__i] + __thisScanline[__i-__delta];
+ }
+ RETURN(self);
+ }
+%}.
+
+ delta := depth // 8 max:1.
delta+1 to:count do:[:i|
thisScanline at:i put:(((thisScanline at:i)+ (thisScanline at:i-delta)) bitAnd:255)
]
@@ -504,7 +558,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
@@ -524,8 +620,10 @@
!
filterScanline:filterType count:count
+ filterType == 0 ifTrue:[^ self].
+
self
- perform:(#(filterNone: filterHorizontal: filterVertical: filterAverage: filterPaeth:) at:filterType+1)
+ perform:(#(filterHorizontal: filterVertical: filterAverage: filterPaeth:) at:filterType)
with:count
"Modified: / 03-05-2011 / 12:13:31 / cg"
@@ -534,6 +632,25 @@
filterVertical:count
"Use the pixel above as a predictor"
+%{
+ if (__isByteArray(__INST(thisScanline))
+ && __isByteArray(__INST(prevScanline))
+ && __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 __i;
+
+ for (__i=0; __i<__count; __i++) {
+ unsigned int __pix = __thisScanline[__i] + __prevScanline[__i];
+ __thisScanline[__i] = __pix;
+ }
+ RETURN(self);
+ }
+%}.
+
1 to:count do:[:i |
thisScanline
at:i
@@ -543,20 +660,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'!
@@ -585,8 +702,17 @@
"Handle interlaced pixels of supported colorTypes.
Untested code - please verify"
- |srcIndex srcMask nPixels dstIndex dstMask x
- bits bitMask rS lS rowIndex|
+ |srcIndex "{ Class: SmallInteger }"
+ srcMask "{ Class: SmallInteger }"
+ nPixels "{ Class: SmallInteger }"
+ dstIndex "{ Class: SmallInteger }"
+ dstMask "{ Class: SmallInteger }"
+ x "{ Class: SmallInteger }"
+ bits "{ Class: SmallInteger }"
+ bitMask "{ Class: SmallInteger }"
+ rS "{ Class: SmallInteger }"
+ lS "{ Class: SmallInteger }"
+ rowIndex "{ Class: SmallInteger }"|
nPixels := width // incX.
srcIndex := 0. srcMask := 0. x := startX.
@@ -702,7 +828,11 @@
"Handle interlaced pixels of supported colorTypes.
Untested code - please verify"
- |srcIndex nPixels dstIndex dstInc bpp|
+ |srcIndex "{ Class: SmallInteger }"
+ nPixels "{ Class: SmallInteger }"
+ dstIndex "{ Class: SmallInteger }"
+ dstInc "{ Class: SmallInteger }"
+ bpp "{ Class: SmallInteger }"|
bpp := bytesPerScanline // width.
@@ -723,7 +853,10 @@
"Handle interlaced pixels of supported colorTypes.
Untested code - please verify"
- |srcIndex nPixels dstIndex dstInc|
+ |srcIndex "{ Class: SmallInteger }"
+ nPixels "{ Class: SmallInteger }"
+ dstIndex "{ Class: SmallInteger }"
+ dstInc "{ Class: SmallInteger }"|
srcIndex := 1.
dstIndex := (y * bytesPerScanline) + (startX * 4) + 1.
@@ -783,7 +916,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.
@@ -794,7 +928,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.
@@ -811,51 +945,56 @@
pngColorType == 0 ifTrue:[
photometric := #blackIs0.
samplesPerPixel := 1.
- bitsPerSample := Array with:depth.
+ bitsPerSample := Array with:bitsPerChannel.
+ depth := bitsPerChannel.
^ true.
].
pngColorType == 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.
].
pngColorType == 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.
].
pngColorType == 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.
].
pngColorType == 6 ifTrue:[
- depth < 8 ifTrue:[
+ bitsPerChannel < 8 ifTrue:[
'PNGReader: invalid colorType/depth combination' infoPrintCR.
^ false.
].
photometric := #rgba.
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.
].