better multiplane dither
authorClaus Gittinger <cg@exept.de>
Sat, 08 Jun 1996 13:02:30 +0200
changeset 802 828038ff0e83
parent 801 a62c835a5a53
child 803 899f7eb32ef2
better multiplane dither
Depth8Image.st
--- a/Depth8Image.st	Fri Jun 07 19:45:15 1996 +0200
+++ b/Depth8Image.st	Sat Jun 08 13:02:30 1996 +0200
@@ -79,13 +79,12 @@
         ^ Color gray:(100 / 255 * value)
     ].
     photometric ~~ #palette ifTrue:[
-        self error:'format not supported'.
-        ^ nil
+        ^ self colorFromValue:value
     ].
     index := value + 1.
     ^ colorMap at:index
 
-    "Modified: 28.5.1996 / 20:54:42 / cg"
+    "Modified: 8.6.1996 / 10:52:48 / cg"
 !
 
 atX:x y:y putValue:aPixelValue
@@ -112,6 +111,152 @@
 
 !Depth8Image methodsFor:'converting'!
 
+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 8-bit values."
+
+    |dH nDither   
+     greyLevels greyMap1 greyMap2
+     bytesPerRow  "{Class: SmallInteger }"
+     bytesPerOutRow  "{Class: SmallInteger }"
+     pixelsPerByte   "{Class: SmallInteger }"
+     outBits
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }" |
+
+    Transcript showCR:'slow ordered dither ..'. Transcript endEntry.
+
+    nDither := ditherMatrix size.
+    dH := nDither / dW.
+
+    w := width.
+    h := height.
+
+    greyLevels := 1 bitShift:depth.
+    pixelsPerByte := 8 / depth.
+
+    bytesPerRow := self bytesPerRow.
+
+    bytesPerOutRow := (w * depth + 7) // 8.
+    outBits := ByteArray uninitializedNew:(bytesPerOutRow * h).
+    (outBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    greyMap1 := self greyMapForRange:(greyLevels-1).                    "/ the pixels
+    greyMap1 := (greyMap1 collect:[:b | b isNil ifTrue:[
+                                            0
+                                        ] ifFalse:[
+                                            b truncated
+                                        ]
+                                  ]) asByteArray.      
+
+    greyMap2 := self greyMapForRange:(greyLevels-1).
+    greyMap2 := (greyMap2 collect:[:el | 
+                                        el isNil ifTrue:[
+                                            0
+                                        ] ifFalse:[
+                                            ((el - el truncated)  "/ the error (0..1)
+                                            * nDither) rounded
+                                        ]]) asByteArray.
+
+"/            "/ get the colors grey value [0 .. 1]
+"/            grey := clr brightness.
+"/
+"/            "/ remap into [0 .. greyLevels-1]
+"/            grey := grey * (greyLevels-1).
+"/
+"/            "/ get threshold pixel [0 .. greyLevels-1]
+"/
+"/            pixel := grey truncated.  
+"/
+"/            "/ compute the error [0..1]
+"/            grey := grey - pixel.
+"/
+"/            "/ map into dither space [0 .. nDither]
+"/            grey := (grey * (nDither)) rounded.
+
+"/            if (__intVal(grey) > __dT) {
+"/                __pixel++;
+"/            }
+
+%{
+    int __dW = __intVal(dW);
+    int __dH = __intVal(dH);
+    int __byte;
+    int __dT, __dO;
+    int __dstIdx = 0;
+    int __srcIdx = 0;
+    int __bitCnt;
+    int __grey, __pixel;
+    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);
+
+    char *__outBits = __ByteArrayInstPtr(outBits)->ba_element;
+    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++];            /* 0..255 */
+
+            __pixel = __greyMap1[__grey];            /* 0..(greyLevels-1) */
+            __dO    = __greyMap2[__grey];            /* 0.. nDither-1) */
+            __dT = __ditherMatrix[__dY + __oX];
+            if (__dO > __dT)
+                __pixel++;
+
+            __oX++;
+            if (__oX == __dW) __oX = 0;
+
+            __byte = (__byte << __intVal(depth)) | __pixel;
+
+            __bitCnt = __bitCnt - __intVal(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
+!
+
 orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
     "return the dithered monochrome bits for the receiver image;
      with a constant ditherMatrix, this can be used for thresholding.
@@ -138,7 +283,7 @@
         ^ nil
     ].
 
-    greyMap := self greyMapForRange:nDither.
+    greyMap := self greyByteMapForRange:nDither.
 
 %{
     int __dW = __intVal(dW);
@@ -1359,12 +1504,6 @@
      x2       "{ Class: SmallInteger }"
      color colors|
 
-    photometric == #palette ifTrue:[
-        colors := colorMap.
-    ] ifFalse:[
-        colors := Array new:256.
-    ].
-
     x1 := xLow.
     x2 := xHigh.
     srcIndex := (width * y) + 1 + x1.
@@ -1404,10 +1543,11 @@
     ].
 
     photometric ~~ #palette ifTrue:[
-        self error:'format not supported'.
-        ^ self
+        ^ super colorsAtY:y from:xLow to:xHigh do:aBlock.
     ].
 
+    colors := colorMap.
+
     x1 to:x2 do:[:x |
         value := bytes at:srcIndex.
         srcIndex := srcIndex + 1.
@@ -1417,7 +1557,7 @@
     ]
 
     "Created: 7.6.1996 / 19:12:35 / cg"
-    "Modified: 7.6.1996 / 19:25:29 / cg"
+    "Modified: 8.6.1996 / 10:17:45 / cg"
 !
 
 valuesAtY:y from:xLow to:xHigh do:aBlock
@@ -1862,5 +2002,5 @@
 !Depth8Image class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/Depth8Image.st,v 1.41 1996-06-07 17:45:15 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/Depth8Image.st,v 1.42 1996-06-08 11:02:30 cg Exp $'
 ! !