--- a/Depth24Image.st Sat Jun 08 13:42:19 1996 +0200
+++ b/Depth24Image.st Sat Jun 08 15:36:53 1996 +0200
@@ -139,6 +139,160 @@
!Depth24Image methodsFor:'converting rgb images'!
+orderedDitheredBitsWithDitherMatrix:ditherMatrix ditherWidth:dW depth:depth
+ "return the bitmap for a dithered depth-bitmap from the image;
+ with a constant ditherMatrix, this can be used for thresholding.
+ Redefined to make use of knowing that pixels are 24-bit values."
+
+ |f dH nDither v range
+ greyMap1 greyMap2 greyLevels outBits
+ bytesPerOutRow "{Class: SmallInteger }"
+ bytesPerRow "{Class: SmallInteger }"
+ w "{Class: SmallInteger }"
+ h "{Class: SmallInteger }"|
+
+ photometric ~~ #rgb ifTrue:[
+ self error:'invalid format'.
+ ^ nil
+ ].
+
+ nDither := ditherMatrix size.
+ dH := nDither / dW.
+
+ w := width.
+ h := height.
+
+ greyLevels := 1 bitShift:depth.
+ bytesPerRow := self bytesPerRow.
+
+ bytesPerOutRow := (w * depth + 7) // 8.
+ outBits := ByteArray uninitializedNew:(bytesPerOutRow * h).
+ (outBits isNil or:[bytes isNil]) ifTrue:[
+ ^ nil
+ ].
+
+ greyMap1 := Array new:256.
+ greyMap2 := Array new:256.
+ range := greyLevels-1.
+ 1 to:256 do:[:i |
+ v := (range / 255 * (i-1)).
+ greyMap1 at:i put:v.
+ greyMap2 at:i put:v.
+ ].
+
+ greyMap1 := (greyMap1 collect:[:b | b isNil ifTrue:[
+ 0
+ ] ifFalse:[
+ b truncated
+ ]
+ ]) asByteArray.
+
+ greyMap2 := (greyMap2 collect:[:el |
+ el isNil ifTrue:[
+ 0
+ ] ifFalse:[
+ ((el - el truncated) "/ the error (0..1)
+ * nDither) rounded
+ ]]) asByteArray.
+%{
+ int __dW = __intVal(dW);
+ int __dH = __intVal(dH);
+ int __byte;
+ int __nDither = __intVal(nDither);
+ int __dT, __dO;
+ int __depth = __intVal(depth);
+ int __dstIdx = 0;
+ int __srcIdx = 0;
+ int __bitCnt;
+ int __grey;
+ int __w = __intVal(w);
+ int __h = __intVal(h);
+ int __x;
+ int __y;
+ int __oX, __oY, __dY;
+ int __nextDst;
+ int __nextSrc;
+ int __bytesPerRow = __intVal(bytesPerRow);
+ int __bytesPerOutRow = __intVal(bytesPerOutRow);
+ int __pixel;
+
+ char *__outBits = __ByteArrayInstPtr(outBits)->ba_element;
+ unsigned char *__ditherMatrix = __ByteArrayInstPtr(ditherMatrix)->ba_element;
+ unsigned char *__bytes = __ByteArrayInstPtr(__INST(bytes))->ba_element;
+ unsigned char *__greyMap1 = __ByteArrayInstPtr(greyMap1)->ba_element;
+ unsigned char *__greyMap2 = __ByteArrayInstPtr(greyMap2)->ba_element;
+
+ __oY = __dY = 0;
+ for (__y=0; __y<__h; __y++) {
+ __nextDst = __dstIdx + __bytesPerOutRow;
+ __nextSrc = __srcIdx + __bytesPerRow;
+
+ __byte = 0;
+ __bitCnt = 8;
+
+ __oX = 0;
+
+ for (__x=0; __x<__w; __x++) {
+ __grey = (__bytes[__srcIdx] * 3) /* 0.3*r + 0.6*g + b -> 0..2550 */
+ + (__bytes[__srcIdx+1] * 6)
+ + __bytes[__srcIdx+2];
+ __grey = __grey / 10; /* 0 .. 255 */
+
+ __pixel = __greyMap1[__grey]; /* 0..(greyLevels-1) */
+ __dO = __greyMap2[__grey]; /* 0.. nDither-1) */
+ __dT = __ditherMatrix[__dY + __oX];
+
+ if (__dO > __dT) /* dither says: next pixel */
+ __pixel++;
+
+ __srcIdx += 3;
+
+ __oX++;
+ if (__oX == __dW) __oX = 0;
+
+ __byte = (__byte << __depth) | __pixel;
+
+ __bitCnt = __bitCnt - __depth;
+ if (__bitCnt == 0) {
+ __outBits[__dstIdx] = __byte;
+ __dstIdx++;
+ __byte = 0;
+ __bitCnt = 8;
+ }
+ }
+
+ if (__bitCnt != 8) {
+ __byte = __byte << __bitCnt;
+ __outBits[__dstIdx] = __byte;
+ }
+
+ __oY++; __dY += __dW;
+ if (__oY == __dH) {
+ __oY = 0;
+ __dY = 0;
+ }
+
+ __srcIdx = __nextSrc;
+ __dstIdx = __nextDst;
+ }
+%}.
+
+ ^ outBits
+
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ i asOrderedDitheredMonochromeImage inspect.
+ i asOrderedDitheredDepth2GrayImage inspect.
+ i asOrderedDitheredDepth4GrayImage inspect.
+ i asOrderedDitheredDepth8GrayImage inspect.
+ "
+
+ "Created: 7.6.1996 / 10:48:06 / cg"
+ "Modified: 7.6.1996 / 11:08:50 / cg"
+!
+
orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
"return the dithered monochrome bits for the receiver image;
with a constant ditherMatrix, this can be used for thresholding.
@@ -191,7 +345,7 @@
int __bytesPerMonoRow = __intVal(bytesPerMonoRow);
char *__monoBits = __ByteArrayInstPtr(monoBits)->ba_element;
- char *__ditherMatrix = __ByteArrayInstPtr(ditherMatrix)->ba_element;
+ unsigned char *__ditherMatrix = __ByteArrayInstPtr(ditherMatrix)->ba_element;
unsigned char *__bytes = __ByteArrayInstPtr(__INST(bytes))->ba_element;
__oY = __dY = 0;
@@ -374,74 +528,53 @@
rgbImageAs8BitGreyFormOn:aDevice
"return an 8-bit greyForm from the rgb picture"
- |greyBits f v
- srcIndex "{ Class: SmallInteger }"
- dstIndex "{ Class: SmallInteger }"
- failed|
+ ^ Form
+ width:width
+ height:height
+ fromArray:(self threshold8BitGreyBits)
+
+ "Modified: 8.6.1996 / 13:58:08 / cg"
+!
+
+rgbImageAs8BitGreyImage
+ "return an 8-bit grey image from the rgb picture.
+ Pixel values are reduced to a 0..255 grey level."
- greyBits := ByteArray uninitializedNew:(width * height).
- failed := false.
-%{
- register unsigned char *srcPtr, *dstPtr;
- register _v;
- register j;
- register i;
+ ^ Depth8Image
+ width:width
+ height:height
+ fromArray:(self threshold8BitGreyBits)
+
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ i rgbImageAs8BitGreyImage inspect
+ "
- if ((__Class(_INST(bytes)) == ByteArray)
- && (__Class(greyBits) == ByteArray)) {
- failed = false;
- srcPtr = _ByteArrayInstPtr(_INST(bytes))->ba_element;
- dstPtr = _ByteArrayInstPtr(greyBits)->ba_element;
- for (i=_intVal(_INST(height)); i>0; i--) {
- for (j=_intVal(_INST(width)); j>0; j--) {
- _v = (*srcPtr * 3); /* 0.3*r + 0.6*g + b */
- _v += (*srcPtr++ * 6);
- _v += *srcPtr++;
- _v /= 10;
- *dstPtr++ = _v >> 4 ;
- }
- }
- }
-%}
-.
- failed ifTrue:[
-"/ the above is equivalent to:
-"/
-"/ srcIndex := 1.
-"/ dstIndex := 1.
-"/
-"/ 1 to:height do:[:h |
-"/ 1 to:width do:[:w |
-"/ |v
-"/ r "{ Class: SmallInteger }"
-"/ g "{ Class: SmallInteger }"
-"/ b "{ Class: SmallInteger }"|
-"/
-"/ r := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/ g := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/ b := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/
-"/ v := ((3 * r) + (6 * g) + (1 * b)) // 10.
-"/ v := v bitShift:-4.
-"/ greyBits at:dstIndex put:v.
-"/ dstIndex := dstIndex + 1
-"/ ]
-"/ ]
- self primitiveFailed.
- ^ nil
- ].
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i rgbImageAs8BitGreyImage asOrderedDitheredGrayImageDepth:2) inspect
+ "
+
+ "
+ |i|
- f := Form width:width height:height depth:8 on:aDevice.
- f isNil ifTrue:[^ nil].
- f initGC.
- aDevice drawBits:greyBits depth:8 width:width height:height
- x:0 y:0
- into:(f id) x:0 y:0
- width:width height:height with:(f gcId).
- ^ f
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i rgbImageAs8BitGreyImage asOrderedDitheredGrayImageDepth:4) inspect
+ "
+
+ "
+ |i|
+
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ i rgbImageAs8BitGreyImage asOrderedDitheredMonochromeImage inspect
+ "
+
+ "Created: 8.6.1996 / 13:58:46 / cg"
+ "Modified: 8.6.1996 / 14:02:05 / cg"
!
rgbImageAsDitheredPseudoFormOn:aDevice
@@ -705,116 +838,43 @@
using a threshold algorithm.
(i.e. grey value < 0.5 -> black, grey value >= 0.5 -> white)."
- |monoBits f
- w "{ Class: SmallInteger }"
- h "{ Class: SmallInteger }"
- r "{ Class: SmallInteger }"
- g "{ Class: SmallInteger }"
- b "{ Class: SmallInteger }"
- v "{ Class: SmallInteger }"
- map rMap gMap bMap
- srcIndex "{ Class: SmallInteger }"
- dstIndex "{ Class: SmallInteger }"
- bits "{ Class: SmallInteger }"
- bitCount "{ Class: SmallInteger }"
- failed |
+ ^ self
+ asThresholdMonochromeFormOn:aDevice
+
+ "
+ |i|
- w := width.
- h := height.
- monoBits := ByteArray uninitializedNew:(((w + 7) // 8) * h).
- failed := true.
-%{
- register unsigned char *srcPtr, *dstPtr;
- register _v, _bits, _bitCount;
- register j;
- register i;
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i asThresholdMonochromeFormOn:Display) inspect
+ "
- if (__isByteArray(_INST(bytes))
- && __isByteArray(monoBits)) {
- failed = false;
- srcPtr = _ByteArrayInstPtr(_INST(bytes))->ba_element;
- dstPtr = _ByteArrayInstPtr(monoBits)->ba_element;
- for (i=_intVal(h); i>0; i--) {
- _bitCount = 0;
- _bits = 0;
- for (j=_intVal(w); j>0; j--) {
- _bits <<= 1;
+ "
+ |i|
- _v = (*srcPtr++ * 3); /* 0.3*r + 0.6*g + b */
- _v += (*srcPtr++ * 6);
- _v += *srcPtr++;
- _v /= 10;
- if (_v & 0x80)
- _bits |= 1;
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i
+ asOrderedDitheredMonochromeImageWithDitherMatrix:#[7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
+ ditherWidth:4) inspect
+ "
- _bitCount++;
- if (_bitCount == 8) {
- *dstPtr++ = _bits;
- _bits = 0;
- _bitCount = 0;
- }
- }
- if (_bitCount != 0) {
- while (_bitCount++ != 8) _bits <<= 1;
- *dstPtr++ = _bits;
- }
- }
- }
-%}.
+ "
+ |i|
- failed ifTrue:[
-"/ the above is equivalent to:
-"/
-"/ srcIndex := 1.
-"/ dstIndex := 1.
-"/ 1 to:h do:[:row |
-"/ bitCount := 0.
-"/ bits := 0.
-"/ 1 to:w do:[:col |
-"/ bits := bits bitShift:1.
-"/
-"/ r := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/ g := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/ b := bytes at:srcIndex.
-"/ srcIndex := srcIndex + 1.
-"/ v := ((3 * r) + (6 * g) + (1 * b)) // 10.
-"/ ((v bitAnd:16r80) == 0) ifFalse:[
-"/ bits := bits bitOr:1
-"/ ].
-"/ bitCount := bitCount + 1.
-"/ (bitCount == 8) ifTrue:[
-"/ monoBits at:dstIndex put:bits.
-"/ dstIndex := dstIndex + 1.
-"/ bits := 0.
-"/ bitCount := 0
-"/ ]
-"/ ].
-"/ (bitCount ~~ 0) ifTrue:[
-"/ [bitCount == 8] whileFalse:[
-"/ bitCount := bitCount + 1.
-"/ bits := bits bitShift:1.
-"/ ].
-"/ monoBits at:dstIndex put:bits.
-"/ dstIndex := dstIndex + 1
-"/ ]
-"/ ]
- self primitiveFailed.
- ^ nil
- ].
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i
+ asOrderedDitheredMonochromeImageWithDitherMatrix:#[5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5]
+ ditherWidth:4) inspect
+ "
+ "
+ |i|
- f := Form width:w height:h depth:1 on:aDevice.
- f isNil ifTrue:[^ nil].
- f initGC.
- (aDevice blackpixel == 0) ifFalse:[
- "have to invert bits"
- f function:#copyInverted
- ].
- aDevice drawBits:monoBits depth:1 width:w height:h
- x:0 y:0
- into:(f id) x:0 y:0 width:w height:h with:(f gcId).
- ^ f
+ i := Image fromFile:'bitmaps/granite.tiff'.
+ (i
+ asOrderedDitheredMonochromeImageWithDitherMatrix:#[4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
+ ditherWidth:4) inspect
+ "
+
+ "Modified: 8.6.1996 / 14:08:21 / cg"
!
rgbImageAsPatternDitheredGreyFormOn:aDevice
@@ -848,6 +908,26 @@
pixel0bytes pixel1bytes ditherPattern
ditherColors first delta|
+ depth := aDevice depth.
+ depth == 1 ifTrue:[
+ ^ self asOrderedDitheredMonochromeFormOn:aDevice
+ ].
+ (depth == 2
+ or:[depth == 4
+ or:[depth == 8]]) ifTrue:[
+ ^ (Form
+ width:width
+ height:height
+ depth:depth)
+ bits:(
+ self
+ orderedDitheredBitsWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
+ ditherWidth:8
+ depth:depth)
+ ].
+
+ "/ funny output depth ....
+
Transcript showCR:'dithering ..'. Transcript endEntry.
h := height.
@@ -879,194 +959,6 @@
w := width.
h := height.
- depth := aDevice depth.
- depth == 1 ifTrue:[
- formBytes := ByteArray uninitializedNew:(w + 7 // 8) * h.
- patterns := Array new:nColors.
- pixel0bytes := ByteArray uninitializedNew:nColors.
- pixel1bytes := ByteArray uninitializedNew:nColors.
-
- "extract dither patterns and values to use for 1/0 bits
- in those from the dithercolors"
-
- 1 to:nColors do:[:i |
- clr := (map at:i) on:aDevice.
- ditherPattern := clr ditherForm.
-
- ditherPattern isNil ifTrue:[
- patterns at:i put:#[2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111].
- pixel0bytes at:i put:clr colorId.
- pixel1bytes at:i put:clr colorId
- ] ifFalse:[
- patterns at:i put:(ditherPattern bits).
- pixel0bytes at:i put:(ditherPattern colorMap at:1) colorId.
- pixel1bytes at:i put:(ditherPattern colorMap at:2) colorId.
- ].
- ].
-
- srcIndex := 1.
- dstIndex := 1.
- mask := 16r80.
- outBits := 0.
- patternOffset := 1.
- 1 to:h do:[:dstY |
- last := nil.
- 1 to:w do:[:dstX |
- r := bytes at:srcIndex.
- g := bytes at:(srcIndex + 1).
- b := bytes at:(srcIndex + 2).
- srcIndex := srcIndex + 3.
-
- v := ((3 * r) + (6 * g) + (1 * b)). "pixel grey value (*10)"
- v == last ifFalse:[
- index := v // 10 + 1. "index into map"
-
- patternBytes := patterns at:index. "dither pattern for color"
- patternBits := patternBytes at:patternOffset. "dither row"
- p0 := pixel0bytes at:index. "value for 0-dither bit"
- p1 := pixel1bytes at:index. "value for 1-dither bit"
- last := v.
- ].
- outBits := outBits bitShift:1.
-
- (patternBits bitAnd:mask) == 0 ifTrue:[
- outBits := outBits bitOr:p0.
- ] ifFalse:[
- outBits := outBits bitOr:p1
- ].
- mask := mask bitShift:-1.
- mask == 0 ifTrue:[
- mask := 16r80.
- formBytes at:dstIndex put:outBits.
- dstIndex := dstIndex + 1.
- outBits := 0
- ]
- ].
- mask == 16r80 ifFalse:[
- [mask == 0] whileFalse:[
- mask := mask bitShift:-1.
- outBits := outBits bitShift:1.
- ].
- formBytes at:dstIndex put:outBits.
- dstIndex := dstIndex + 1.
- mask := 16r80.
- outBits := 0
- ].
- patternOffset := patternOffset + 1.
- patternOffset == 9 ifTrue:[
- patternOffset := 1
- ]
- ].
- f := Form width:w height:h fromArray:formBytes.
- ^ f
- ].
-
- depth == 2 ifTrue:[
- formBytes := ByteArray uninitializedNew:(w * 2 + 7 // 8) * h.
- patterns := Array new:nColors.
- pixel0bytes := ByteArray uninitializedNew:nColors.
- pixel1bytes := ByteArray uninitializedNew:nColors.
-
- "extract dither patterns and values to use for 1/0 bits
- in those from the dithercolors"
-
- 1 to:nColors do:[:i |
- clr := (map at:i) on:aDevice.
- ditherPattern := clr ditherForm.
-
- ditherPattern isNil ifTrue:[
- patterns at:i put:#[2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111
- 2r11111111].
- pixel0bytes at:i put:clr colorId.
- pixel1bytes at:i put:clr colorId
- ] ifFalse:[
- patterns at:i put:(ditherPattern bits).
- pixel0bytes at:i put:(ditherPattern colorMap at:1) colorId.
- pixel1bytes at:i put:(ditherPattern colorMap at:2) colorId.
- ].
- ].
-
- srcIndex := 1.
- dstIndex := 1.
- mask := 16r80.
- outBits := 0.
- patternOffset := 1.
- 1 to:h do:[:dstY |
- last := nil.
- outCount := 0.
- mask := 16r80.
- outBits := 0.
- 1 to:w do:[:dstX |
- r := bytes at:srcIndex.
- srcIndex := srcIndex + 1.
- g := bytes at:srcIndex.
- srcIndex := srcIndex + 1.
- b := bytes at:srcIndex.
- srcIndex := srcIndex + 1.
-
- v := ((3 * r) + (6 * g) + (1 * b)). "pixel grey value (*10)"
- v == last ifFalse:[
- index := v // 10 + 1. "index into map"
-
- patternBytes := patterns at:index. "dither pattern for color"
- patternBits := patternBytes at:patternOffset. "dither row"
- p0 := pixel0bytes at:index. "value for 0-dither bit"
- p1 := pixel1bytes at:index. "value for 1-dither bit"
- last := v.
- ].
- outBits := outBits bitShift:2.
-
- (patternBits bitAnd:mask) == 0 ifTrue:[
- outBits := outBits bitOr:p0.
- ] ifFalse:[
- outBits := outBits bitOr:p1
- ].
- mask := mask bitShift:-1.
- outCount := outCount + 1.
- outCount == 4 ifTrue:[
- formBytes at:dstIndex put:outBits.
- dstIndex := dstIndex + 1.
- outBits := 0.
- outCount := 0.
- mask == 0 ifTrue:[
- mask := 16r80.
- ]
- ]
- ].
- (outCount == 0) ifFalse:[
- [outCount == 4] whileFalse:[
- outCount := outCount + 1.
- outBits := outBits bitShift:2.
- ].
- formBytes at:dstIndex put:outBits.
- dstIndex := dstIndex + 1.
- ].
- patternOffset := patternOffset + 1.
- patternOffset == 9 ifTrue:[
- patternOffset := 1
- ]
- ].
- f := Form width:w height:h depth:depth.
- f initGC.
- f device drawBits:formBytes depth:2
- width:w height:h x:0 y:0
- into:f id x:0 y:0 width:w height:h with:f gcId.
- ^ f
- ].
-
"draw each pixel using dither color (let others do the dithering)
although the code is simple, its very slow"
@@ -1106,7 +998,7 @@
].
^ f
- "Modified: 28.5.1996 / 20:54:06 / cg"
+ "Modified: 8.6.1996 / 15:19:34 / cg"
!
rgbImageAsPseudoFormOn:aDevice
@@ -1630,6 +1522,41 @@
^ form
"Modified: 21.10.1995 / 19:30:11 / cg"
+!
+
+threshold8BitGreyBits
+ "return the bits for an 8-bit grey image from the receiver.
+ Special code, since this is a common case."
+
+ |greyBits
+ srcIndex "{ Class: SmallInteger }"
+ dstIndex "{ Class: SmallInteger }"|
+
+ greyBits := ByteArray uninitializedNew:(width * height).
+%{
+ register unsigned char *srcPtr, *dstPtr;
+ register __v;
+ register i;
+
+ if ((__Class(__INST(bytes)) == ByteArray)
+ && (__Class(greyBits) == ByteArray)) {
+ srcPtr = __ByteArrayInstPtr(__INST(bytes))->ba_element;
+ dstPtr = __ByteArrayInstPtr(greyBits)->ba_element;
+
+ i = __intVal(__INST(height)) * __intVal(__INST(width));
+
+ for (; i > 0; i--) {
+ __v = (srcPtr[0] * 3); /* 3*r + 6*g + b ; 0 .. 2550 */
+ __v += (srcPtr[1] * 6);
+ __v += srcPtr[2];
+ srcPtr += 3;
+ __v /= 10; /* 0..255 */
+ *dstPtr++ = __v ;
+ }
+ }
+%}.
+ ^ greyBits
+
! !
!Depth24Image methodsFor:'enumerating'!
@@ -1913,5 +1840,5 @@
!Depth24Image class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview/Depth24Image.st,v 1.28 1996-06-08 11:42:19 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview/Depth24Image.st,v 1.29 1996-06-08 13:34:35 cg Exp $'
! !