Image.st
changeset 809 f66955a8200e
parent 808 f548a3c6ca8c
child 813 8bc17dba7a02
--- a/Image.st	Sat Jun 08 15:36:53 1996 +0200
+++ b/Image.st	Mon Jun 10 15:21:51 1996 +0200
@@ -304,6 +304,46 @@
                  inspect
                                                                         [exEnd]
 
+      a 2/2/0 rgb image (i.e. no blue):
+                                                                        [exBegin]
+         |i|
+
+         i := Depth4Image
+                    width:4
+                    height:4
+                    fromArray:#[ 16r01 16r23
+                                 16r45 16r67
+                                 16r89 16rab
+                                 16rcd 16ref ].
+         i photometric:#rgb.
+         i samplesPerPixel:3.
+         i bitsPerSample:#(2 2 0).
+
+         i := i magnifiedBy:30.
+         i inspect.
+                                                                        [exEnd]
+
+
+      a 0/0/4 rgb image (i.e. no red or green):
+                                                                        [exBegin]
+         |i|
+
+         i := Depth4Image
+                    width:4
+                    height:4
+                    fromArray:#[ 16r01 16r23
+                                 16r45 16r67
+                                 16r89 16rab
+                                 16rcd 16ref ].
+         i photometric:#rgb.
+         i samplesPerPixel:3.
+         i bitsPerSample:#(0 0 4).
+
+         i := i magnifiedBy:30.
+         i inspect.
+                                                                        [exEnd]
+
+
       a 2plane greyscale image:
                                                                         [exBegin]
         ((Depth2Image
@@ -429,8 +469,15 @@
         Lobby := Registry new.
         ObjectMemory addDependent:self.
 
-        "define algorithm to use for dithering - currently only nil or #pattern supported"
-        DitherAlgorithm := #pattern.   "will be changed to error as soon as implemented"
+        "/ define the algorithm to use for dithering - 
+        "/ supported values are:
+        "/      #threshold
+        "/      #ordered
+        "/      #floydSteinberg
+        "/      #burkes
+
+        DitherAlgorithm := #floydSteinberg.   
+
         (Display notNil and:[Display hasGrayscales]) ifFalse:[
             NumberOfDitherColors := 64
         ] ifTrue:[
@@ -446,7 +493,7 @@
         CollectGarbageWhenRunningOutOfColors := false
     ]
 
-    "Modified: 28.5.1996 / 21:12:30 / cg"
+    "Modified: 10.6.1996 / 12:28:22 / cg"
 !
 
 initializeFileFormatTable
@@ -738,7 +785,7 @@
     inStream isNil ifTrue:[
         inStream := Smalltalk bitmapFileStreamFor:name.
         inStream isNil ifTrue:[
-            ('IMAGE: ' , aFileName , ' does not exist or is not readable') infoPrintNL.
+            ('IMAGE: ' , aFileName , ' does not exist or is not readable') infoPrintCR.
             ^ nil
         ].
         name := 'bitmaps/' , name.
@@ -810,21 +857,28 @@
      Image fromFile:'bitmaps/hello_world.icon'
     "
 
-    "Modified: 7.3.1996 / 19:18:13 / cg"
+    "Modified: 10.6.1996 / 14:36:18 / cg"
 ! !
 
 !Image class methodsFor:'misc'!
 
 dither:aSymbol
-    "define how to dither - #pattern, #error or none;
-     error diffusion dithering is currently not implemented,
-     pattern dither is currently very slow."
+    "define how to dither - 
+        #threshold, or nil        -> no dither
+        #pattern, or #ordered     -> orderedDither (ugly, but fast)
+        #error or #floydSteinberg -> errorDiffusion; much better
+        #burkes                   -> errorDiffusion; even better."
 
     DitherAlgorithm := aSymbol
 
-    "Image dither:#pattern"
-    "Image dither:#error"
-    "Image dither:nil"
+    "
+     Image dither:#pattern
+     Image dither:#floydSteinberg
+     Image dither:#burkes
+     Image dither:nil
+    "
+
+    "Modified: 10.6.1996 / 12:27:09 / cg"
 !
 
 numberOfDitherColors:n
@@ -1498,6 +1552,57 @@
 
 !Image methodsFor:'converting'!
 
+asBurkesDitheredMonochromeImage
+    "return a burkes dithered monochrome image from the receiver image."
+
+    |monoBits|
+
+    monoBits := self burkesDitheredMonochromeBits.
+    ^ (Depth1Image width:width height:height fromArray:monoBits) photometric:#blackIs0
+
+    "
+     |i|
+
+     i := Image fromFile:'garfield.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "Modified: 10.6.1996 / 12:18:32 / cg"
+    "Created: 10.6.1996 / 12:34:44 / cg"
+!
+
 asCachedImage
     "return the receiver associated to the current screens device.
      For ST-80 compatibility 
@@ -1508,6 +1613,270 @@
     "Modified: 23.4.1996 / 11:10:32 / cg"
 !
 
+asErrorDitheredMonochromeImage
+    "return an error-diffusion dithered monochrome image from the receiver image."
+
+    DitherAlgorithm == #burkes ifTrue:[
+        ^ self asBurkesDitheredMonochromeImage
+    ].
+    DitherAlgorithm == #stevensonArce ifTrue:[
+        ^ self asStevensonArgceDitheredMonochromeImage
+    ].
+    ^ self asFloydSteinbergDitheredMonochromeImage
+
+    "
+     |i|
+
+     i := Image fromFile:'garfield.gif'.
+     i inspect.
+     i asErrorDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     i asErrorDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     i asErrorDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "Modified: 10.6.1996 / 14:22:30 / cg"
+!
+
+asFloydSteinbergDitheredGrayFormOn:aDevice
+    "return a dithered depth-x grey form from the receiver image."
+
+    |f depth bits|
+
+    depth := aDevice depth.
+    depth == 1 ifTrue:[
+        "/ for monochrome, there is specialized
+        "/ monochrome dither code available
+
+        bits := self floydSteinbergDitheredMonochromeBits.
+    ] ifFalse:[
+        bits := self floydSteinbergDitheredBitsDepth:depth.
+    ].
+
+    f := Form width:width height:height depth:depth.
+    f bits:bits.
+    ^ f on:aDevice
+
+    "
+     |i f|
+
+     i := Image fromFile:'bitmaps/claus.gif'.
+     f := i asFloydSteinbergDitheredGrayFormOn:Display.
+    "
+
+    "Modified: 8.6.1996 / 15:29:51 / cg"
+    "Created: 10.6.1996 / 14:11:39 / cg"
+!
+
+asFloydSteinbergDitheredGrayImageDepth:depth
+    "return a floyd-steinberg dithered image from the receiver image."
+
+    |ditheredBits|
+
+    depth == 1 ifTrue:[
+        ^ self asFloydSteinbergDitheredMonochromeImage
+    ].
+
+    ditheredBits := self floydSteinbergDitheredBitsDepth:depth.
+    ^ (self class implementorForDepth:depth)
+        width:width height:height fromArray:ditheredBits
+
+    "
+     |i|
+
+     i := Image fromFile:'garfield.gif'.
+     i inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:4) inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:4) inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:4) inspect.
+    "
+
+    "Created: 10.6.1996 / 12:33:47 / cg"
+    "Modified: 10.6.1996 / 14:40:26 / cg"
+!
+
+asFloydSteinbergDitheredGreyImageDepth:depth
+    "return a floyd-steinberg dithered image from the receiver image."
+
+    |ditheredBits|
+
+    depth == 1 ifTrue:[
+        ^ self asFloydSteinbergDitheredMonochromeImage
+    ].
+
+    ditheredBits := self floydSteinbergDitheredBitsDepth:depth.
+    ditheredBits isNil ifTrue:[
+        ^ nil
+    ].
+    ^ (self class implementorForDepth:depth)
+        width:width height:height fromArray:ditheredBits
+
+    "
+     |i|
+
+     i := Image fromFile:'bitmaps/red-ball.gif'.
+     i inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:4) inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:4) inspect.
+
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     (i asOrderedDitheredGrayImageDepth:1) inspect.
+     (i asOrderedDitheredGrayImageDepth:2) inspect.
+     (i asOrderedDitheredGrayImageDepth:4) inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'bitmaps/granite.tiff'.
+     i inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:4) inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGreyImageDepth:4) inspect.
+    "
+
+    "Created: 10.6.1996 / 12:33:47 / cg"
+    "Modified: 10.6.1996 / 15:09:50 / cg"
+!
+
+asFloydSteinbergDitheredMonochromeImage
+    "return a floyd-steinberg dithered monochrome image from the receiver image."
+
+    |monoBits|
+
+    monoBits := self floydSteinbergDitheredMonochromeBits.
+    ^ (Depth1Image width:width height:height fromArray:monoBits) photometric:#blackIs0
+
+    "
+     |i|
+
+     i := Image fromFile:'garfield.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "Created: 10.6.1996 / 12:33:47 / cg"
+    "Modified: 10.6.1996 / 12:47:20 / cg"
+!
+
 asFormOn:aDevice
     "get a device form, with best possible approximation.
      remember it in case someone asks again."
@@ -1587,132 +1956,6 @@
     ^ form
 !
 
-asOrderedDitheredDepth2GrayImage
-    "return a dithered depth2 grey image from the receiver image.
-     Uses an 8x8 dithermatrix."
-
-    ^ Depth2Image
-        width:width
-        height:height
-        fromArray:(
-            self
-                orderedDitheredBitsWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
-                ditherWidth:8
-                depth:2)
-
-    "
-     |i i2|
-
-     i := Image fromFile:'bitmaps/claus.gif'.
-     i2 := i asOrderedDitheredDepth2GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'/cdrom/icons/a/a11.ico') magnifiedBy:10.
-     i2 := i asOrderedDitheredDepth2GrayImage
-
-
-     |i i2|
-
-     i := Image fromFile:'bitmaps/garfield.gif'.
-     i2 := i asOrderedDitheredDepth2GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'bitmaps/PasteButton.tiff') magnifiedBy:10.
-     i2 := i asOrderedDitheredDepth2GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'bitmaps/blue-ball.gif') magnifiedBy:1.
-     i2 := i asOrderedDitheredDepth2GrayImage
-
-
-     |i i2|
-
-     i := Image fromFile:'bitmaps/granite.tiff'.
-     i2 := i asOrderedDitheredDepth2GrayImage
-    "
-
-    "Modified: 7.6.1996 / 17:59:15 / cg"
-    "Created: 7.6.1996 / 18:03:54 / cg"
-!
-
-asOrderedDitheredDepth4GrayImage
-    "return a dithered depth4 gray image from the receiver image.
-     Uses an 8x8 dithermatrix."
-
-    ^ Depth4Image
-        width:width
-        height:height
-        fromArray:(
-            self
-                orderedDitheredBitsWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
-                ditherWidth:8
-                depth:4)
-
-    "
-     |i i2|
-
-     i := Image fromFile:'bitmaps/claus.gif'.
-     i2 := i asOrderedDitheredDepth4GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'/cdrom/icons/a/a11.ico') magnifiedBy:10.
-     i2 := i asOrderedDitheredDepth4GrayImage
-
-
-     |i i2|
-
-     i := Image fromFile:'bitmaps/garfield.gif'.
-     i2 := i asOrderedDitheredDepth4GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'bitmaps/PasteButton.tiff') magnifiedBy:10.
-     i2 := i asOrderedDitheredDepth4GrayImage
-
-
-     |i i2|
-
-     i := (Image fromFile:'bitmaps/blue-ball.gif') magnifiedBy:1.
-     i2 := i asOrderedDitheredDepth4GrayImage
-
-
-     |i i2|
-
-     i := Image fromFile:'bitmaps/granite.tiff'.
-     i2 := i asOrderedDitheredDepth4GrayImage
-    "
-
-    "Modified: 7.6.1996 / 16:58:34 / cg"
-    "Created: 7.6.1996 / 18:03:04 / cg"
-!
-
-asOrderedDitheredDepth8GrayImage
-    "return a dithered depth8 grey image from the receiver image.
-     Uses an 8x8 dithermatrix.
-     This is provided for protocol completeness - 8bit grey images are
-     usually not dithered at all."
-
-    ^ Depth8Image
-        width:width
-        height:height
-        fromArray:(
-            self
-                orderedDitheredBitsWithDitherMatrix:(self class orderedDitherMatrixOfSize:8)
-                ditherWidth:8
-                depth:8)
-
-    "Modified: 7.6.1996 / 18:08:20 / cg"
-!
-
 asOrderedDitheredGrayFormOn:aDevice
     "return a dithered depth-x grey form from the receiver image.
      Uses an 8x8 dithermatrix."
@@ -1930,44 +2173,44 @@
 "/        ditherWidth:8
 
     "
-     |i i2|
+     |i|
 
      i := Image fromFile:'bitmaps/claus.gif'.
-     i2 := i asOrderedDitheredMonochromeImage
-
-
-     |i i2|
+     i asOrderedDitheredMonochromeImage inspect
+
+
+     |i|
 
      i := (Image fromFile:'/cdrom/icons/a/a11.ico') magnifiedBy:10.
-     i2 := i asOrderedDitheredMonochromeImage
-
-
-     |i i2|
+     i asOrderedDitheredMonochromeImage inspect
+
+
+     |i|
 
      i := Image fromFile:'bitmaps/garfield.gif'.
-     i2 := i asOrderedDitheredMonochromeImage
-
-
-     |i i2|
+     i asOrderedDitheredMonochromeImage inspect
+
+
+     |i|
 
      i := (Image fromFile:'bitmaps/PasteButton.tiff') magnifiedBy:10.
-     i2 := i asOrderedDitheredMonochromeImage
-
-
-     |i i2|
+     i asOrderedDitheredMonochromeImage inspect
+
+
+     |i|
 
      i := (Image fromFile:'bitmaps/blue-ball.gif') magnifiedBy:1.
-     i2 := i asOrderedDitheredMonochromeImage
-
-
-     |i i2|
+     i asOrderedDitheredMonochromeImage inspect
+
+
+     |i|
 
      i := Image fromFile:'bitmaps/granite.tiff'.
-     i2 := i asOrderedDitheredMonochromeImage
+     i asOrderedDitheredMonochromeImage inspect
     "
 
     "Created: 7.6.1996 / 15:02:07 / cg"
-    "Modified: 7.6.1996 / 16:58:34 / cg"
+    "Modified: 10.6.1996 / 11:15:09 / cg"
 !
 
 asOrderedDitheredMonochromeImageWithDitherMatrix:ditherMatrix ditherWidth:dW
@@ -2033,6 +2276,58 @@
     "Modified: 7.6.1996 / 17:23:47 / cg"
 !
 
+asStevensonArceDitheredMonochromeImage
+    "return a floyd-steinberg dithered monochrome image from the receiver image."
+
+    |monoBits|
+
+    monoBits := self stevensonArceDitheredMonochromeBits.
+    ^ (Depth1Image width:width height:height fromArray:monoBits) photometric:#blackIs0
+
+    "
+     |i|
+
+     i := Image fromFile:'garfield.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asStevensonArceDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Image fromFile:'claus.gif'.
+     i inspect.
+     i asFloydSteinbergDitheredMonochromeImage inspect.
+     i asBurkesDitheredMonochromeImage inspect.
+     i asStevensonArceDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "
+     |i|
+
+     i := Depth4Image
+             width:4 
+             height:4
+             fromArray:#[ 
+                            16r01 16r23
+                            16r45 16r67
+                            16r89 16rab
+                            16rcd 16ref 
+                        ].
+     i := i magnifiedBy:30.
+     i inspect.
+     i asStevensonArceDitheredMonochromeImage inspect.
+     i asOrderedDitheredMonochromeImage inspect.
+    "
+
+    "Created: 10.6.1996 / 12:38:29 / cg"
+    "Modified: 10.6.1996 / 13:54:14 / cg"
+!
+
 asThresholdGrayImageDepth:depth
     "return a thresholded depth-x grey image from the receiver image."
 
@@ -2059,24 +2354,27 @@
                 depth:depth)
 
     "
-     |i i1 i2 i4 i8|
+     |i|
 
      i := Image fromFile:'bitmaps/claus.gif'.
-     i1 := i asThresholdGrayImageDepth:1.
-     i1 inspect.
-
-     i2 := i asThresholdGrayImageDepth:2.
-     i2 inspect.
-
-     i4 := i asThresholdGrayImageDepth:4.
-     i4 inspect.
-
-     i8 := i asThresholdGrayImageDepth:8.
-     i8 inspect.
+     (i asThresholdGrayImageDepth:1) inspect.
+     (i asThresholdGrayImageDepth:2) inspect.
+     (i asThresholdGrayImageDepth:4) inspect.
+     (i asThresholdGrayImageDepth:8) inspect.
+
+     (i asOrderedDitheredGrayImageDepth:1) inspect.
+     (i asOrderedDitheredGrayImageDepth:2) inspect.
+     (i asOrderedDitheredGrayImageDepth:4) inspect.
+     (i asOrderedDitheredGrayImageDepth:8) inspect.
+
+     (i asFloydSteinbergDitheredGrayImageDepth:1) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:2) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:4) inspect.
+     (i asFloydSteinbergDitheredGrayImageDepth:8) inspect.
     "
 
     "Created: 7.6.1996 / 18:13:33 / cg"
-    "Modified: 7.6.1996 / 19:39:37 / cg"
+    "Modified: 10.6.1996 / 14:20:56 / cg"
 !
 
 asThresholdMonochromeFormOn:aDevice
@@ -2243,7 +2541,7 @@
         ]
     ].
 
-    "Modified: 23.4.1996 / 11:11:00 / cg"
+    "Modified: 8.6.1996 / 16:02:03 / cg"
 !
 
 fromImage:anImage
@@ -2368,215 +2666,6 @@
     ].
     deviceForm := self asFormOn:aDevice.
     device := aDevice
-!
-
-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.
-     Works for any source depths / photometric, 
-     but very very slow since each pixel is processed individually.
-     Redefined by some subclasses for more performance (D8Image)"
-
-    |f last dH nDither   
-     greyLevels
-     dstIndex        "{Class: SmallInteger }"
-     nextDst         
-     bytesPerOutRow  "{Class: SmallInteger }"
-     pixelsPerByte   "{Class: SmallInteger }"
-     outBits
-     w               "{Class: SmallInteger }"
-     h               "{Class: SmallInteger }"
-     bitCnt          "{Class: SmallInteger }"
-     byte            "{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.
-
-    bytesPerOutRow := (w * depth + 7) // 8.
-    outBits := ByteArray uninitializedNew:(bytesPerOutRow * h).
-    (outBits isNil or:[bytes isNil]) ifTrue:[
-        ^ nil
-    ].
-
-    dstIndex := 1.
-    0 to:(h-1) do:[:y |
-        nextDst := dstIndex + bytesPerOutRow.
-        byte := 0.
-        bitCnt := 8.
-
-        "/ this is the representaion independent (but slow)
-        "/ inner loop - it extracts colors from the receiver
-        
-        self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
-            |dstClr grey dT pixel|
-
-            "/ 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.
-
-%{
-            int __dW = __intVal(dW);
-            int __byte = __intVal(byte);
-            int __dT;
-            int __dstIdx;
-            int __pixel;
-            int __bitCnt = __intVal(bitCnt);
-
-            __dT = __ByteArrayInstPtr(ditherMatrix)
-                        ->ba_element[__intVal(x) % __dW 
-                                     + (__intVal(y) % __intVal(dH)) * __dW];
-
-            __pixel = __intVal(pixel);
-
-            if (__intVal(grey) > __dT) {
-                __pixel++;
-            }
-            __byte = (__byte << __intVal(depth)) | __pixel;
-        
-            __bitCnt = __bitCnt - __intVal(depth);
-            if (__bitCnt == 0) {
-                __dstIdx = __intVal(dstIndex);
-                __ByteArrayInstPtr(outBits)->ba_element[__dstIdx-1] = __byte;
-                __dstIdx = __dstIdx + 1;
-                dstIndex = __MKSMALLINT(__dstIdx);
-                __byte = 0;
-                __bitCnt = 8;
-            }
-            byte = __MKSMALLINT(__byte);
-            bitCnt = __MKSMALLINT(__bitCnt);
-%}.
-            0
-
-        ].
-        bitCnt ~~ 8 ifTrue:[
-            byte := byte bitShift:bitCnt.
-            outBits at:dstIndex put:byte.
-        ].
-        dstIndex := nextDst.
-    ].
-
-    ^ outBits
-!
-
-orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
-    "return the bitmap for a dithered monochrome bitmap from the image;
-     with a constant ditherMatrix, this can be used for thresholding.
-     Works for any source depths / photometric, 
-     but very very slow since each pixel is processed individually.
-     Redefined by some subclasses for more performance (D8Image)"
-
-    |f last dH nDither   
-     clr0 clr1
-     dstIndex        "{Class: SmallInteger }"
-     nextDst         
-     bytesPerMonoRow "{Class: SmallInteger }"
-     monoBits
-     w               "{Class: SmallInteger }"
-     h               "{Class: SmallInteger }"
-     bitCnt          "{Class: SmallInteger }"
-     byte            "{Class: SmallInteger }" |
-
-    Transcript showCR:'slow ordered dither ..'. Transcript endEntry.
-
-    nDither := ditherMatrix size.
-    dH := nDither / dW.
-
-    w := width.
-    h := height.
-
-    bytesPerMonoRow := (w + 7) // 8.
-    monoBits := ByteArray uninitializedNew:(bytesPerMonoRow * h).
-    (monoBits isNil or:[bytes isNil]) ifTrue:[
-        ^ nil
-    ].
-
-    dstIndex := 1.
-    0 to:(h-1) do:[:y |
-        nextDst := dstIndex + bytesPerMonoRow.
-        byte := 0.
-        bitCnt := 8.
-        self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
-            |dstClr grey dT|
-
-            "/ get the colors grey value [0 .. 1]
-            grey := clr brightness.
-
-            "/ map into dither space [0 .. nDither]
-            grey := (grey * (nDither)) rounded.
-
-%{
-            int __dW = __intVal(dW);
-            int __byte = __intVal(byte);
-            int __dT;
-            int __dstIdx;
-            int __bitCnt = __intVal(bitCnt);
-
-            __dT = __ByteArrayInstPtr(ditherMatrix)
-                        ->ba_element[__intVal(x) % __dW 
-                                     + (__intVal(y) % __intVal(dH)) * __dW];
-
-            __byte = __byte << 1;
-            if (__intVal(grey) > __dT) {
-                __byte = __byte | 1;            /* white */
-            }
-            __bitCnt = __bitCnt - 1;
-            if (__bitCnt == 0) {
-                __dstIdx = __intVal(dstIndex);
-                __ByteArrayInstPtr(monoBits)->ba_element[__dstIdx-1] = __byte;
-                __dstIdx = __dstIdx + 1;
-                dstIndex = __MKSMALLINT(__dstIdx);
-                __byte = 0;
-                __bitCnt = 8;
-            }
-            byte = __MKSMALLINT(__byte);
-            bitCnt = __MKSMALLINT(__bitCnt);
-%}.
-            0
-
-"/            "/ compare
-"/            dT := ditherMatrix at:(x \\ dW) + (y \\ dH * dW) + 1.
-"/
-"/            byte := byte bitShift:1.
-"/            grey < dT ifTrue:[
-"/                byte := byte bitOr:1.
-"/            ].
-"/            bitCnt := bitCnt - 1.
-"/            bitCnt == 0 ifTrue:[
-"/                monoBits at:dstIndex put:byte.
-"/                dstIndex := dstIndex + 1.
-"/                byte := 0.
-"/                bitCnt := 8.
-"/            ].
-
-        ].
-        bitCnt ~~ 8 ifTrue:[
-            byte := byte bitShift:bitCnt.
-            monoBits at:dstIndex put:byte.
-        ].
-        dstIndex := nextDst.
-    ].
-
-    ^ monoBits
 ! !
 
 !Image methodsFor:'converting greyscale images'!
@@ -2588,8 +2677,8 @@
 
     nPlanes := samplesPerPixel.
     (nPlanes == 2) ifTrue:[
-	'IMAGE: alpha plane ignored' errorPrintNL.
-	nPlanes := 1
+        'IMAGE: alpha plane ignored' errorPrintNL.
+        nPlanes := 1
     ].
 
     pictureDepth := bitsPerSample at:1.
@@ -2597,70 +2686,70 @@
     "monochrome is very easy ..."
 
     (pictureDepth == 1) ifTrue:[
-	^ Form width:width height:height fromArray:bytes on:aDevice
+        ^ Form width:width height:height fromArray:bytes on:aDevice
     ].
 
     (aDevice visualType == #StaticGray) ifTrue:[
-	(aDevice depth == pictureDepth) ifTrue:[
-
-	    "greyscale is easy, if the depths match"
-
-	    f := Form width:width height:height depth:pictureDepth on:aDevice.
-	    f isNil ifTrue:[^ nil].
-	    f initGC.
-
-	    "if device has white at the opposite corner ..."
-	    ((aDevice blackpixel == 0) == (photometric == #blackIs0)) ifFalse:[
-		"have to invert bits"
-		f function:#copyInverted
-	    ].
-	    aDevice drawBits:bytes depth:pictureDepth width:width height:height
-			    x:0 y:0
-			 into:(f id)
-			    x:0 y:0 width:width height:height with:(f gcId).
-	    ^ f
-	].
-
-	"the image has more greylevels than the display - dither"
+        (aDevice depth == pictureDepth) ifTrue:[
+
+            "greyscale is easy, if the depths match"
+
+            f := Form width:width height:height depth:pictureDepth on:aDevice.
+            f isNil ifTrue:[^ nil].
+            f initGC.
+
+            "if device has white at the opposite corner ..."
+            ((aDevice blackpixel == 0) == (photometric == #blackIs0)) ifFalse:[
+                "have to invert bits"
+                f function:#copyInverted
+            ].
+            aDevice drawBits:bytes depth:pictureDepth width:width height:height
+                            x:0 y:0
+                         into:(f id)
+                            x:0 y:0 width:width height:height with:(f gcId).
+            ^ f
+        ].
+
+        "the image has more greylevels than the display - dither"
 
 "
 coming soon ...
-	DitherAlgorithm == #error ifTrue:[
-	    ^ self greyImageAsErrorDitheredGreyFormOn:aDevice
-	].
+        DitherAlgorithm == #error ifTrue:[
+            ^ self greyImageAsErrorDitheredGreyFormOn:aDevice
+        ].
 "
-	DitherAlgorithm == #pattern ifTrue:[
-	    ^ self greyImageAsPatternDitheredGreyFormOn:aDevice
-	].
-
-	"no dither, simply cut off information"
-	(aDevice depth == 1) ifTrue:[
-	    "for monochrome, there is a special method to do this"
-	    ^ self greyImageAsMonoFormOn:aDevice
-	].
-	"the general case, will take as many bits from the image
-	 as possible for the device"
-	^ self greyImageAsGreyFormOn:aDevice
+        DitherAlgorithm == #pattern ifTrue:[
+            ^ self greyImageAsPatternDitheredGrayFormOn:aDevice
+        ].
+
+        "no dither, simply cut off information"
+        (aDevice depth == 1) ifTrue:[
+            "for monochrome, there is a special method to do this"
+            ^ self greyImageAsMonoFormOn:aDevice
+        ].
+        "the general case, will take as many bits from the image
+         as possible for the device"
+        ^ self greyImageAsGrayFormOn:aDevice
     ].
 
 
     (aDevice visualType == #PseudoColor 
     or:[aDevice visualType == #GrayScale
     or:[aDevice visualType == #StaticColor]]) ifTrue:[
-	^ self greyImageAsPseudoFormOn:aDevice
+        ^ self greyImageAsPseudoFormOn:aDevice
     ].
 
     (aDevice visualType == #TrueColor) ifTrue:[
-	^ self greyImageAsTrueColorFormOn:aDevice
+        ^ self greyImageAsTrueColorFormOn:aDevice
     ].
 
     self error:'cannot convert this format'.
     ^ nil
 
-    "Modified: 11.12.1995 / 18:55:01 / cg"
-!
-
-greyImageAsGreyFormOn:aDevice
+    "Modified: 10.6.1996 / 14:41:05 / cg"
+!
+
+greyImageAsGrayFormOn:aDevice
     "return an 8-bit Form from the grey image"
 
     |wideBits pictureDepth f map nplanes ncells
@@ -2674,8 +2763,8 @@
      shift4   "{ Class: SmallInteger }" |
 
     (aDevice depth == 8) ifFalse:[
-	'IMAGE: non-8 plane displays not supported' errorPrintNL.
-	^ self greyImageAsMonoFormOn:aDevice
+        'IMAGE: non-8 plane displays not supported' errorPrintNL.
+        ^ self greyImageAsMonoFormOn:aDevice
     ].
 
     pictureDepth := bitsPerSample at:1.
@@ -2688,8 +2777,8 @@
     nplanes := 8.
     ncells := 256.
     [aDevice ncells < ncells] whileTrue:[
-	nplanes := nplanes - 1.
-	ncells := ncells // 2
+        nplanes := nplanes - 1.
+        ncells := ncells // 2
     ].
 
     "prepare translation table"
@@ -2701,34 +2790,36 @@
 
     inverse := aDevice blackpixel ~~ 0.
     photometric == #blackIs0 ifFalse:[
-	inverse := inverse not
+        inverse := inverse not
     ].
     mapSize := map size.
     1 to:mapSize do:[:index |
-	oldValue := index - 1.
-	newValue := oldValue bitShift:shift.
-	newValue := newValue bitOr:(oldValue bitShift:shift2).
-	newValue := newValue bitOr:(oldValue bitShift:shift3).
-	newValue := newValue bitOr:(oldValue bitShift:shift4).
-	inverse ifTrue:[
-	    map at:(map size - index + 1) put:newValue
-	] ifFalse:[
-	    map at:index put:newValue
-	]
+        oldValue := index - 1.
+        newValue := oldValue bitShift:shift.
+        newValue := newValue bitOr:(oldValue bitShift:shift2).
+        newValue := newValue bitOr:(oldValue bitShift:shift3).
+        newValue := newValue bitOr:(oldValue bitShift:shift4).
+        inverse ifTrue:[
+            map at:(map size - index + 1) put:newValue
+        ] ifFalse:[
+            map at:index put:newValue
+        ]
     ].
     bytes expandPixels:pictureDepth
-		width:width 
-	       height:height
-		 into:wideBits
-	      mapping:map.
+                width:width 
+               height:height
+                 into:wideBits
+              mapping:map.
 
     f := Form width:width height:height depth:8 on:aDevice.
     f isNil ifTrue:[^ nil].
     f initGC.
     aDevice drawBits:wideBits depth:8 width:width height:height
-		       x:0 y:0
-		    into:(f id) x:0 y:0 width:width height:height with:(f gcId).
+                       x:0 y:0
+                    into:(f id) x:0 y:0 width:width height:height with:(f gcId).
     ^ f
+
+    "Created: 10.6.1996 / 14:40:45 / cg"
 !
 
 greyImageAsMonoFormOn:aDevice
@@ -2739,7 +2830,7 @@
     "Modified: 8.6.1996 / 15:22:35 / cg"
 !
 
-greyImageAsPatternDitheredGreyFormOn:aDevice
+greyImageAsPatternDitheredGrayFormOn:aDevice
     "return a dithered greyForm from the grey image.
      Works for any source/destination depths, but very very slow
      since each pixel is processed individually.
@@ -2787,6 +2878,7 @@
     ^ f
 
     "Modified: 7.6.1996 / 19:11:46 / cg"
+    "Created: 10.6.1996 / 14:41:10 / cg"
 !
 
 greyImageAsPseudoFormOn:aDevice
@@ -3006,37 +3098,37 @@
     |type ddepth|
 
     (ddepth := aDevice depth) == 1 ifTrue:[
-	^ self paletteImageAsMonoFormOn:aDevice
+        ^ self paletteImageAsMonoFormOn:aDevice
     ].
 
     ((type := aDevice visualType) == #StaticGray) ifTrue:[
-	ddepth == 8 ifTrue:[
-	    ^ self paletteImageAsGreyFormOn:aDevice
-	].
-
-	DitherAlgorithm == #pattern ifTrue:[
-	    ^ self paletteImageAsPatternDitheredGreyFormOn:aDevice
-	].
-
-	ddepth == 2 ifTrue:[
-	    ^ self paletteImageAs2PlaneFormOn:aDevice
-	].
-
-	^ self paletteImageAsMonoFormOn:aDevice
+        ddepth == 8 ifTrue:[
+            ^ self paletteImageAsGray8FormOn:aDevice
+        ].
+
+        DitherAlgorithm == #pattern ifTrue:[
+            ^ self paletteImageAsPatternDitheredGrayFormOn:aDevice
+        ].
+
+        ddepth == 2 ifTrue:[
+            ^ self paletteImageAs2PlaneFormOn:aDevice
+        ].
+
+        ^ self paletteImageAsMonoFormOn:aDevice
     ].
     (type == #TrueColor) ifTrue:[
-	^ self paletteImageAsTrueColorFormOn:aDevice
+        ^ self paletteImageAsTrueColorFormOn:aDevice
     ].
     (type == #PseudoColor) ifTrue:[
-	^ self paletteImageAsPseudoFormOn:aDevice
+        ^ self paletteImageAsPseudoFormOn:aDevice
     ].
     (type == #StaticColor) ifTrue:[
-	^ self paletteImageAsPseudoFormOn:aDevice
+        ^ self paletteImageAsPseudoFormOn:aDevice
     ].
     "/ dump fallback: every device should implement b&w images ...
     ^ self paletteImageAsMonoFormOn:aDevice
 
-    "Modified: 11.12.1995 / 16:34:52 / cg"
+    "Modified: 10.6.1996 / 14:41:52 / cg"
 !
 
 paletteImageAsGreyFormOn:aDevice
@@ -3046,15 +3138,21 @@
 !
 
 paletteImageAsMonoFormOn:aDevice
-    "return a 1-bit mono-deviceForm from the palette image"
-
-    ^ self subclassResponsibility
-!
-
-paletteImageAsPatternDitheredGreyFormOn:aDevice
+    "return a 1-bit mono-deviceForm from the palette image.
+     the result is a thresholded form, with white for
+     brightness values above 50%, black below"
+
+    ^ self asThresholdMonochromeFormOn:aDevice
+
+    "Modified: 10.6.1996 / 14:27:51 / cg"
+!
+
+paletteImageAsPatternDitheredGrayFormOn:aDevice
     "return a dithered grey-deviceForm from the palette image."
 
     ^ self subclassResponsibility
+
+    "Created: 10.6.1996 / 14:41:56 / cg"
 !
 
 paletteImageAsPseudoFormOn:aDevice
@@ -3306,10 +3404,12 @@
     ^ self subclassResponsibility
 !
 
-rgbImageAs8BitGreyFormOn:aDevice
+rgbImageAs8BitGrayFormOn:aDevice
     "return an 8-bit greyForm from the rgb picture"
 
     ^ self subclassResponsibility
+
+    "Created: 10.6.1996 / 14:42:03 / cg"
 !
 
 rgbImageAsFormOn:aDevice
@@ -3320,15 +3420,17 @@
 
     visual := aDevice visualType.
     (visual == #StaticGray) ifTrue:[
-	^ self rgbImageAsGreyFormOn:aDevice
+        ^ self rgbImageAsGrayFormOn:aDevice
     ].
     (visual == #TrueColor) ifTrue:[
-	^ self rgbImageAsTrueColorFormOn:aDevice
+        ^ self rgbImageAsTrueColorFormOn:aDevice
     ].
     ^ self rgbImageAsPseudoFormOn:aDevice
-!
-
-rgbImageAsGreyFormOn:aDevice
+
+    "Modified: 10.6.1996 / 14:44:09 / cg"
+!
+
+rgbImageAsGrayFormOn:aDevice
     "convert an rgb image to a grey device-form on aDevice
      (for greyscale displays)"
 
@@ -3338,39 +3440,41 @@
 
     "I have specially tuned methods for monochrome"
     (deviceDepth == 1) ifTrue:[
-	DitherAlgorithm == #error ifTrue:[
-	    ^ self rgbImageAsErrorDitheredGreyFormOn:aDevice
-	].
-	DitherAlgorithm == #pattern ifTrue:[
-	    ^ self rgbImageAsPatternDitheredGreyFormOn:aDevice
-	].
-	^ self rgbImageAsMonoFormOn:aDevice
+        DitherAlgorithm == #error ifTrue:[
+            ^ self rgbImageAsErrorDitheredGrayFormOn:aDevice
+        ].
+        DitherAlgorithm == #pattern ifTrue:[
+            ^ self rgbImageAsPatternDitheredGrayFormOn:aDevice
+        ].
+        ^ self rgbImageAsMonoFormOn:aDevice
     ].
 
     "and for 2plane greyscale (i.e. NeXTs)"
     (deviceDepth == 2) ifTrue:[
-	DitherAlgorithm == #error  ifTrue:[
-	    ^ self rgbImageAsErrorDitheredGreyFormOn:aDevice
-	].
-	DitherAlgorithm == #pattern  ifTrue:[
-	    ^ self rgbImageAsPatternDitheredGreyFormOn:aDevice
-	].
-	^ self rgbImageAs2PlaneFormOn:aDevice
+        DitherAlgorithm == #error  ifTrue:[
+            ^ self rgbImageAsErrorDitheredGrayFormOn:aDevice
+        ].
+        DitherAlgorithm == #pattern  ifTrue:[
+            ^ self rgbImageAsPatternDitheredGrayFormOn:aDevice
+        ].
+        ^ self rgbImageAs2PlaneFormOn:aDevice
     ].
 
     (deviceDepth == 8) ifTrue:[
-	^ self rgbImageAs8BitGreyFormOn:aDevice
+        ^ self rgbImageAs8BitGrayFormOn:aDevice
     ].
 
     "mhmh need another converter ...
      till then we do:"
     DitherAlgorithm == #error  ifTrue:[
-	^ self rgbImageAsErrorDitheredGreyFormOn:aDevice
+        ^ self rgbImageAsErrorDitheredGrayFormOn:aDevice
     ].
     DitherAlgorithm == #pattern  ifTrue:[
-	^ self rgbImageAsPatternDitheredGreyFormOn:aDevice
+        ^ self rgbImageAsPatternDitheredGrayFormOn:aDevice
     ].
     ^ self rgbImageAsMonoFormOn:aDevice
+
+    "Modified: 10.6.1996 / 14:44:58 / cg"
 !
 
 rgbImageAsMonoFormOn:aDevice
@@ -3378,16 +3482,27 @@
      using a threshold algorithm. 
      (i.e. grey value < 0.5 -> black, grey value >= 0.5 -> white)."
 
-    ^ self subclassResponsibility
-!
-
-rgbImageAsPatternDitheredGreyFormOn:aDevice
+    ^ self
+        asThresholdMonochromeFormOn:aDevice
+
+    "
+     |i|
+
+     i := Image fromFile:'bitmaps/granite.tiff'.
+     (i asThresholdMonochromeFormOn:Display) inspect
+    "
+
+    "Modified: 10.6.1996 / 12:31:23 / cg"
+!
+
+rgbImageAsPatternDitheredGrayFormOn:aDevice
     "return a dithered greyForm for aDevice from the palette picture.
-     works for any destination depth.
-     A slow algorithm, using draw into the form (which indirectly does
-     the dither) - should be rewritten."
-
-    ^ self subclassResponsibility
+     works for any destination depth."
+
+    ^ self asOrderedDitheredGrayFormOn:aDevice
+
+    "Modified: 10.6.1996 / 14:19:21 / cg"
+    "Created: 10.6.1996 / 14:44:17 / cg"
 !
 
 rgbImageAsPseudoFormOn:aDevice
@@ -3516,6 +3631,1046 @@
     "Modified: 29.5.1996 / 10:52:30 / cg"
 ! !
 
+!Image methodsFor:'dither helpers'!
+
+burkesDitheredMonochromeBits
+    "return the bitmap for a dithered monochrome bitmap from the image.
+     Works for any source depths / photometric"
+
+    |dstIndex        "{Class: SmallInteger }"
+     nextDst         "{Class: SmallInteger }"
+     bytesPerMonoRow "{Class: SmallInteger }"
+     monoBits greyValues
+     errorArray
+     errorArray1
+     e t
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" 
+     grey dT 
+     eR eRB eB eLB |
+
+    self depth > 12 ifTrue:[
+        ^ self floydSteinbergDitheredMonochromeBits
+    ].
+
+    w := width.
+    h := height.
+
+    bytesPerMonoRow := (w + 7) // 8.
+    monoBits := ByteArray uninitializedNew:(bytesPerMonoRow * h).
+    (monoBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    errorArray := Array new:(w+4).
+    errorArray1 := Array new:(w+4) withAll:0.
+
+    dstIndex := 1.
+
+    "/ fetch scaled brightness values outside of loop into a table;
+    "/ use table-value in loop
+
+    greyValues := self greyMapForRange:(255*1024).
+    
+    0 to:(h-1) do:[:y |
+        nextDst := dstIndex + bytesPerMonoRow.
+        byte := 0.
+        bitCnt := 8.
+
+        t := errorArray.
+        errorArray := errorArray1.
+        errorArray1 := t.
+
+        errorArray1 atAllPut:0.
+
+        self valuesAtY:y from:0 to:(w-1) do:[:x :pixel |
+            |eP "{Class: SmallInteger }" 
+             eD 
+             eI "{Class: SmallInteger }" 
+             xE "{Class: SmallInteger }"
+             xN "{Class: SmallInteger }" |
+
+            "/ get the colors grey value [0 .. 1]
+            grey := greyValues at:(pixel + 1).
+
+            "/ adjust error
+            xE := x + 2 + 1.
+            grey := (grey + (errorArray at:xE)).
+
+            byte := byte bitShift:1.
+            grey > (127*1024) ifTrue:[
+                byte := byte bitOr:1.      "/ white
+                e := grey - (255*1024)
+            ] ifFalse:[
+                e := grey                  "/ black
+            ].
+
+            e ~= 0 ifTrue:[
+                "/ distribute the error:
+                "/                  XX  8  4
+                "/             2  4  8  4  2
+
+                eD := e.
+                eI := e // 32.
+
+                eP := eI * 8. eD := eD - eP.
+
+                xN := xE + 1.
+                errorArray at:xN put:(errorArray at:xN) + eP.
+
+                eD := eD - eP.
+                errorArray1 at:xE put:(errorArray1 at:xE) + eP.
+
+                eP := eI * 4. eD := eD - eP.
+                xN := xE + 2.
+                errorArray at:xN put:(errorArray at:xN) + eP.
+
+                eD := eD - eP.
+                xN := xE - 1.
+                errorArray1 at:xN put:(errorArray1 at:xN) + eP.
+
+                eD := eD - eP.
+                xN := xE + 1.
+                errorArray1 at:xN put:(errorArray1 at:xN) + eP.
+
+                eP := eI * 2. eD := eD - eP.
+                xN := xE - 2.
+                errorArray1 at:xN put:(errorArray1 at:xN) + eP.
+
+                eD := eD.
+                xN := xE + 2.
+                errorArray1 at:xN put:(errorArray1 at:xN) + eP.
+            ].
+
+            bitCnt := bitCnt - 1.
+            bitCnt == 0 ifTrue:[
+                monoBits at:dstIndex put:byte.
+                dstIndex := dstIndex + 1.
+                byte := 0.
+                bitCnt := 8.
+            ].
+
+        ].
+        bitCnt ~~ 8 ifTrue:[
+            byte := byte bitShift:bitCnt.
+            monoBits at:dstIndex put:byte.
+        ].
+
+        dstIndex := nextDst.
+    ].
+
+    ^ monoBits
+
+    "Created: 10.6.1996 / 12:18:20 / cg"
+    "Modified: 10.6.1996 / 13:16:33 / cg"
+!
+
+floydSteinbergDitheredBitsDepth:depth
+    "return the bitmap for a dithered depth bitmap from the image.
+     Works for any source depths / photometric, 
+     but very slow since each pixel is processed individually.
+     Redefined by some subclasses for more performance (D8Image)"
+
+    |dstIndex        "{Class: SmallInteger }"
+     nextDst         "{Class: SmallInteger }"
+     bytesPerOutRow  "{Class: SmallInteger }"
+     outBits greyValues greyErrors greyPixels greyLevels
+     errorArray
+     nextErrorArray
+     e t
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" 
+     grey dT 
+     eR eRB eB eLB |
+
+    depth > 8 ifTrue:[
+        self error:'unimplemented conversion'.
+        ^ nil
+    ].
+
+    w := width.
+    h := height.
+
+    bytesPerOutRow := ((w * depth) + 7) // 8.
+    outBits := ByteArray uninitializedNew:(bytesPerOutRow * h).
+    (outBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    greyLevels := (1 bitShift:depth) - 1.
+
+    errorArray := Array new:w+2.
+    nextErrorArray := Array new:w+2.
+
+    nextErrorArray atAllPut:0.
+
+    dstIndex := 1.
+
+    self depth <= 12 ifTrue:[
+        "/ fetch scaled brightness values outside of loop into a table;
+        "/ use table-value in loop
+
+        greyValues := self greyMapForRange:(greyLevels).
+
+        greyPixels := greyValues collect:[:v | v isNil ifTrue:[
+                                                   0
+                                               ] ifFalse:[
+                                                   v truncated]].
+
+        greyPixels := ByteArray withAll:greyPixels.
+
+        greyErrors := greyValues collect:[:v | v isNil ifTrue:[
+                                                   0
+                                               ] ifFalse:[
+                                                   (v - v truncated)
+                                               ]].
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerOutRow.
+            byte := 0.
+            bitCnt := 8.
+
+            t := errorArray.
+            errorArray := nextErrorArray.
+            nextErrorArray := t.
+
+            nextErrorArray atAllPut:0.
+
+            self valuesAtY:y from:0 to:(w-1) do:[:x :value |
+                |e eD pixel error
+                 e16 
+                 xE "{ Class: SmallInteger }" 
+                 xN "{ Class: SmallInteger }" |
+
+                pixel := greyPixels at:(value + 1).
+
+                "/ adjust error
+                xE := x + 2.
+                error := (greyErrors at:(value + 1)) + (errorArray at:xE).
+
+                byte := byte bitShift:depth.
+                error > 0.5 ifTrue:[
+                    pixel := pixel + 1.      
+                    e := error - 1.0
+                ] ifFalse:[
+                    e := error              
+                ].
+                byte := byte bitOr:pixel.
+
+                e ~= 0 ifTrue:[
+                    eD := e.
+                    e16 := e / 16.
+
+                    eR  := e16 * 7.              "/ 7/16 to right
+                    eRB := e16 * 1.              "/ 1/16 to right below
+                    eB  := e16 * 5.              "/ 5/16 to below
+                    eLB := eD - eR - eRB - eB.  "/ 3/16 to left below
+
+                    xN := xE + 1.
+                    eR ~= 0 ifTrue:[
+                        errorArray     at:xN put:(errorArray at:xN) + eR.
+                    ].
+                    eRB ~= 0 ifTrue:[
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eRB.
+                    ].
+                    eB ~= 0 ifTrue:[
+                        nextErrorArray at:xE put:(nextErrorArray at:xE) + eB.
+                    ].
+                    eLB ~= 0 ifTrue:[
+                        xN := xE - 1.
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eLB.
+                    ].
+                ].
+
+                bitCnt := bitCnt - depth.
+                bitCnt == 0 ifTrue:[
+                    outBits at:dstIndex put:byte.
+                    dstIndex := dstIndex + 1.
+                    byte := 0.
+                    bitCnt := 8.
+                ].
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                outBits at:dstIndex put:byte.
+            ].
+
+            dstIndex := nextDst.
+        ].
+    ] ifFalse:[
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerOutRow.
+            byte := 0.
+            bitCnt := 8.
+
+            t := errorArray.
+            errorArray := nextErrorArray.
+            nextErrorArray := t.
+
+            nextErrorArray atAllPut:0.
+
+            self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
+                |e eD pixel error
+                 e16 
+                 xE "{ Class: SmallInteger }" 
+                 xN "{ Class: SmallInteger }" |
+
+                grey := (clr brightness * greyLevels).
+                pixel := grey truncated.
+                error := grey - pixel.
+
+                "/ adjust error
+                xE := x + 2.
+                error := error + (errorArray at:xE).
+
+                byte := byte bitShift:depth.
+                error > 0.5 ifTrue:[
+                    pixel := pixel + 1.      
+                    e := error - 1.0
+                ] ifFalse:[
+                    e := error              
+                ].
+
+                byte := byte bitOr:pixel.
+
+                e ~= 0 ifTrue:[
+                    eD := e.
+                    e16 := e / 16.
+
+                    eR  := e16 * 7.              "/ 7/16 to right
+                    eRB := e16 * 1.              "/ 1/16 to right below
+                    eB  := e16 * 5.              "/ 5/16 to below
+                    eLB := eD - eR - eRB - eB.  "/ 3/16 to left below
+
+                    xN := xE + 1.
+                    eR ~= 0 ifTrue:[
+                        errorArray     at:xN put:(errorArray at:xN) + eR.
+                    ].
+                    eRB ~= 0 ifTrue:[
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eRB.
+                    ].
+                    eB ~= 0 ifTrue:[
+                        nextErrorArray at:xE put:(nextErrorArray at:xE) + eB.
+                    ].
+                    eLB ~= 0 ifTrue:[
+                        xN := xE - 1.
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eLB.
+                    ].
+                ].
+
+                bitCnt := bitCnt - depth.
+                bitCnt == 0 ifTrue:[
+                    outBits at:dstIndex put:byte.
+                    dstIndex := dstIndex + 1.
+                    byte := 0.
+                    bitCnt := 8.
+                ].
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                outBits at:dstIndex put:byte.
+            ].
+
+            dstIndex := nextDst.
+        ].
+    ].
+
+    ^ outBits
+
+    "Created: 10.6.1996 / 13:28:22 / cg"
+    "Modified: 10.6.1996 / 15:09:07 / cg"
+!
+
+floydSteinbergDitheredMonochromeBits
+    "return the bitmap for a dithered monochrome bitmap from the image.
+     Works for any source depths / photometric, 
+     but very very slow since each pixel is processed individually.
+     Redefined by some subclasses for more performance (D8Image)"
+
+    |dstIndex        "{Class: SmallInteger }"
+     nextDst         "{Class: SmallInteger }"
+     bytesPerMonoRow "{Class: SmallInteger }"
+     monoBits greyValues
+     errorArray
+     nextErrorArray
+     e eD t
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" 
+     grey dT 
+     eR eRB eB eLB |
+
+    w := width.
+    h := height.
+
+    bytesPerMonoRow := (w + 7) // 8.
+    monoBits := ByteArray uninitializedNew:(bytesPerMonoRow * h).
+    (monoBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    errorArray := Array new:w+2.
+    nextErrorArray := Array new:w+2.
+
+    nextErrorArray atAllPut:0.
+
+    dstIndex := 1.
+
+    self depth <= 12 ifTrue:[
+        "/ fetch scaled brightness values outside of loop into a table;
+        "/ use table-value in loop
+
+        greyValues := self greyMapForRange:(255 * 1024).
+        greyValues := greyValues collect:[:v | v isNil ifTrue:[
+                                                   0
+                                               ] ifFalse:[
+                                                   v rounded
+                                               ]].
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerMonoRow.
+            byte := 0.
+            bitCnt := 8.
+
+            t := errorArray.
+            errorArray := nextErrorArray.
+            nextErrorArray := t.
+
+            nextErrorArray atAllPut:0.
+
+            self valuesAtY:y from:0 to:(w-1) do:[:x :pixel |
+                |eI "{ Class: SmallInteger }" 
+                 xE "{ Class: SmallInteger }" 
+                 xN "{ Class: SmallInteger }" |
+
+                "/ get the colors grey value [0 .. 1]
+                grey := greyValues at:(pixel + 1).
+
+                "/ adjust error
+                xE := x + 2.
+                grey := (grey + (errorArray at:xE)).
+
+                byte := byte bitShift:1.
+                grey > (127*1024) ifTrue:[
+                    byte := byte bitOr:1.      "/ white
+                    e := grey - (255*1024)
+                ] ifFalse:[
+                    e := grey                  "/ black
+                ].
+
+                e ~= 0 ifTrue:[
+                    eD := e.
+                    eI := e // 16.
+
+                    eR  := eI * 7.              "/ 7/16 to right
+                    eRB := eI * 1.              "/ 1/16 to right below
+                    eB  := eI * 5.              "/ 5/16 to below
+                    eLB := eD - eR - eRB - eB.  "/ 3/16 to left below
+
+                    xN := xE + 1.
+                    eR ~= 0 ifTrue:[
+                        errorArray     at:xN put:(errorArray at:xN) + eR.
+                    ].
+                    eRB ~= 0 ifTrue:[
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eRB.
+                    ].
+                    eB ~= 0 ifTrue:[
+                        nextErrorArray at:xE put:(nextErrorArray at:xE) + eB.
+                    ].
+                    eLB ~= 0 ifTrue:[
+                        xN := xE - 1.
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eLB.
+                    ].
+                ].
+
+                bitCnt := bitCnt - 1.
+                bitCnt == 0 ifTrue:[
+                    monoBits at:dstIndex put:byte.
+                    dstIndex := dstIndex + 1.
+                    byte := 0.
+                    bitCnt := 8.
+                ].
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                monoBits at:dstIndex put:byte.
+            ].
+
+            dstIndex := nextDst.
+        ].
+    ] ifFalse:[
+        'IMAGE: slow floydSteinberg dither ..' infoPrintCR.
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerMonoRow.
+            byte := 0.
+            bitCnt := 8.
+
+            t := errorArray.
+            errorArray := nextErrorArray.
+            nextErrorArray := t.
+
+            nextErrorArray atAllPut:0.
+
+            self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
+                |eI "{ Class: SmallInteger }" 
+                 xE "{ Class: SmallInteger }" 
+                 xN "{ Class: SmallInteger }" |
+
+                "/ get the colors grey value [0 .. 1]
+                grey := (clr brightness * 255).
+
+                "/ adjust error
+                xE := x + 2.
+                grey := (grey + (errorArray at:xE)) rounded.
+
+                byte := byte bitShift:1.
+                grey > 127 ifTrue:[
+                    byte := byte bitOr:1.      "/ white
+                    e := grey - 255
+                ] ifFalse:[
+                    e := grey                  "/ black
+                ].
+
+                e ~= 0 ifTrue:[
+                    eD := e.
+                    eI := e // 16.
+                    eR  := eI * 7.              "/ 7/16 to right
+                    eRB := eI * 1.              "/ 1/16 to right below
+                    eB  := eI * 5.              "/ 5/16 to below
+                    eLB := eD - eR - eRB - eB.  "/ 3/16 to left below
+
+                    xN := xE + 1.
+                    eR ~= 0 ifTrue:[
+                        errorArray     at:xN put:(errorArray at:xN) + eR.
+                    ].
+                    eRB ~= 0 ifTrue:[
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eRB.
+                    ].
+                    eB ~= 0 ifTrue:[
+                        nextErrorArray at:xE put:(nextErrorArray at:xE) + eB.
+                    ].
+                    eLB ~= 0 ifTrue:[
+                        xN := xE - 1.
+                        nextErrorArray at:xN put:(nextErrorArray at:xN) + eLB.
+                    ].
+                ].
+
+                bitCnt := bitCnt - 1.
+                bitCnt == 0 ifTrue:[
+                    monoBits at:dstIndex put:byte.
+                    dstIndex := dstIndex + 1.
+                    byte := 0.
+                    bitCnt := 8.
+                ].
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                monoBits at:dstIndex put:byte.
+            ].
+
+            dstIndex := nextDst.
+        ].
+    ].
+
+    ^ monoBits
+
+    "Created: 8.6.1996 / 16:39:46 / cg"
+    "Modified: 10.6.1996 / 15:12:11 / cg"
+!
+
+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.
+     Works for any source depths / photometric, 
+     but very very slow since each pixel is processed individually.
+     Redefined by some subclasses for more performance (D8Image)"
+
+    |f last dH nDither   
+     greyLevels greyValues greyPixels greyErrors
+     dstIndex        "{Class: SmallInteger }"
+     nextDst         
+     bytesPerOutRow  "{Class: SmallInteger }"
+     pixelsPerByte   "{Class: SmallInteger }"
+     outBits
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" |
+
+    depth > 8 ifTrue:[
+        'IMAGE: unimplemented orderedDither conversion' errorPrintCR.
+        ^ nil
+    ].
+
+    nDither := ditherMatrix size.
+    dH := nDither / dW.
+
+    w := width.
+    h := height.
+
+    greyLevels := 1 bitShift:depth.
+    pixelsPerByte := 8 / depth.
+
+    bytesPerOutRow := (w * depth + 7) // 8.
+    outBits := ByteArray uninitializedNew:(bytesPerOutRow * h).
+    (outBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    dstIndex := 1.
+
+    self bitsPerPixel <= 12 ifTrue:[
+        "/ fetch scaled brightness values outside of loop into a table;
+        "/ use table-value in loop
+
+        greyValues := self greyMapForRange:(greyLevels-1).
+        greyPixels := greyValues collect:[:v | v isNil ifTrue:[
+                                                   0
+                                               ] ifFalse:[
+                                                   v truncated]].
+        greyPixels := ByteArray withAll:greyPixels.
+
+        greyErrors := greyValues collect:[:v | v isNil ifTrue:[
+                                                   0
+                                               ] ifFalse:[
+                                                   ((v - v truncated) * nDither) rounded
+                                               ]].
+        greyErrors := ByteArray withAll:greyErrors.
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerOutRow.
+            byte := 0.
+            bitCnt := 8.
+
+            self valuesAtY:y from:0 to:(w-1) do:[:x :value |
+%{
+                int __dW = __intVal(dW);
+                int __byte = __intVal(byte);
+                int __value = __intVal(value);
+                int __dT;
+                int __dstIdx;
+                int __pixel, __grey;
+                int __bitCnt = __intVal(bitCnt);
+                unsigned char *__greyPixels = __ByteArrayInstPtr(greyPixels)->ba_element;
+                unsigned char *__greyErrors = __ByteArrayInstPtr(greyErrors)->ba_element;
+
+                __pixel = __greyPixels[__value];
+                __grey = __greyErrors[__value];
+
+                __dT = __ByteArrayInstPtr(ditherMatrix)
+                            ->ba_element[__intVal(x) % __dW 
+                                         + (__intVal(y) % __intVal(dH)) * __dW];
+
+                if (__grey > __dT) {
+                    __pixel++;
+                }
+                __byte = (__byte << __intVal(depth)) | __pixel;
+
+                __bitCnt = __bitCnt - __intVal(depth);
+                if (__bitCnt == 0) {
+                    __dstIdx = __intVal(dstIndex);
+                    __ByteArrayInstPtr(outBits)->ba_element[__dstIdx-1] = __byte;
+                    __dstIdx = __dstIdx + 1;
+                    dstIndex = __MKSMALLINT(__dstIdx);
+                    __byte = 0;
+                    __bitCnt = 8;
+                }
+                byte = __MKSMALLINT(__byte);
+                bitCnt = __MKSMALLINT(__bitCnt);
+%}.
+                0
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                outBits at:dstIndex put:byte.
+            ].
+            dstIndex := nextDst.
+        ].
+    ] ifFalse:[
+        Transcript showCR:'slow ordered dither ..'. Transcript endEntry.
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerOutRow.
+            byte := 0.
+            bitCnt := 8.
+
+            "/ this is the representaion independent (but slow)
+            "/ inner loop - it extracts colors from the receiver
+            
+            self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
+                |dstClr grey dT pixel|
+
+                "/ 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.
+
+%{
+                int __dW = __intVal(dW);
+                int __byte = __intVal(byte);
+                int __dT;
+                int __dstIdx;
+                int __pixel;
+                int __bitCnt = __intVal(bitCnt);
+
+                __dT = __ByteArrayInstPtr(ditherMatrix)
+                            ->ba_element[__intVal(x) % __dW 
+                                         + (__intVal(y) % __intVal(dH)) * __dW];
+
+                __pixel = __intVal(pixel);
+
+                if (__intVal(grey) > __dT) {
+                    __pixel++;
+                }
+                __byte = (__byte << __intVal(depth)) | __pixel;
+            
+                __bitCnt = __bitCnt - __intVal(depth);
+                if (__bitCnt == 0) {
+                    __dstIdx = __intVal(dstIndex);
+                    __ByteArrayInstPtr(outBits)->ba_element[__dstIdx-1] = __byte;
+                    __dstIdx = __dstIdx + 1;
+                    dstIndex = __MKSMALLINT(__dstIdx);
+                    __byte = 0;
+                    __bitCnt = 8;
+                }
+                byte = __MKSMALLINT(__byte);
+                bitCnt = __MKSMALLINT(__bitCnt);
+%}.
+                0
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                outBits at:dstIndex put:byte.
+            ].
+            dstIndex := nextDst.
+        ].
+    ].
+    ^ outBits
+!
+
+orderedDitheredMonochromeBitsWithDitherMatrix:ditherMatrix ditherWidth:dW
+    "return the bitmap for a dithered monochrome bitmap from the image;
+     with a constant ditherMatrix, this can be used for thresholding.
+     Works for any source depths / photometric, 
+     but very very slow since each pixel is processed individually.
+     Redefined by some subclasses for more performance (D8Image)"
+
+    |f last dH nDither   
+     greyValues
+     dstIndex        "{Class: SmallInteger }"
+     nextDst         "{Class: SmallInteger }"
+     bytesPerMonoRow "{Class: SmallInteger }"
+     monoBits
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" |
+
+    nDither := ditherMatrix size.
+    dH := nDither / dW.
+
+    w := width.
+    h := height.
+
+    bytesPerMonoRow := (w + 7) // 8.
+    monoBits := ByteArray uninitializedNew:(bytesPerMonoRow * h).
+    (monoBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    dstIndex := 1.
+
+    self bitsPerPixel <= 12 ifTrue:[
+        "/ fetch scaled brightness values outside of loop into a table;
+        "/ use table-value in loop
+
+        greyValues := self greyByteMapForRange:nDither.
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerMonoRow.
+            byte := 0.
+            bitCnt := 8.
+            self valuesAtY:y from:0 to:(w-1) do:[:x :value |
+%{
+                int __dW = __intVal(dW);
+                int __byte = __intVal(byte);
+                int __dT;
+                int __dstIdx;
+                int __bitCnt = __intVal(bitCnt);
+                int __grey;
+                unsigned char *__greyValues = __ByteArrayInstPtr(greyValues)->ba_element;
+
+                __grey = __greyValues[__intVal(value)];
+
+                __dT = __ByteArrayInstPtr(ditherMatrix)
+                            ->ba_element[__intVal(x) % __dW 
+                                         + (__intVal(y) % __intVal(dH)) * __dW];
+
+                __byte = __byte << 1;
+                if (__grey > __dT) {
+                    __byte = __byte | 1;            /* white */
+                }
+                __bitCnt = __bitCnt - 1;
+                if (__bitCnt == 0) {
+                    __dstIdx = __intVal(dstIndex);
+                    __ByteArrayInstPtr(monoBits)->ba_element[__dstIdx-1] = __byte;
+                    __dstIdx = __dstIdx + 1;
+                    dstIndex = __MKSMALLINT(__dstIdx);
+                    __byte = 0;
+                    __bitCnt = 8;
+                }
+                byte = __MKSMALLINT(__byte);
+                bitCnt = __MKSMALLINT(__bitCnt);
+%}.
+                0
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                monoBits at:dstIndex put:byte.
+            ].
+            dstIndex := nextDst.
+        ].
+    ] ifFalse:[
+        Transcript showCR:'slow ordered dither ..'. Transcript endEntry.
+
+        0 to:(h-1) do:[:y |
+            nextDst := dstIndex + bytesPerMonoRow.
+            byte := 0.
+            bitCnt := 8.
+            self colorsAtY:y from:0 to:(w-1) do:[:x :clr |
+                |dstClr grey dT|
+
+                "/ get the colors grey value [0 .. 1]
+                grey := clr brightness.
+
+                "/ map into dither space [0 .. nDither]
+                grey := (grey * (nDither)) rounded.
+
+%{
+                int __dW = __intVal(dW);
+                int __byte = __intVal(byte);
+                int __dT;
+                int __dstIdx;
+                int __bitCnt = __intVal(bitCnt);
+
+                __dT = __ByteArrayInstPtr(ditherMatrix)
+                            ->ba_element[__intVal(x) % __dW 
+                                         + (__intVal(y) % __intVal(dH)) * __dW];
+
+                __byte = __byte << 1;
+                if (__intVal(grey) > __dT) {
+                    __byte = __byte | 1;            /* white */
+                }
+                __bitCnt = __bitCnt - 1;
+                if (__bitCnt == 0) {
+                    __dstIdx = __intVal(dstIndex);
+                    __ByteArrayInstPtr(monoBits)->ba_element[__dstIdx-1] = __byte;
+                    __dstIdx = __dstIdx + 1;
+                    dstIndex = __MKSMALLINT(__dstIdx);
+                    __byte = 0;
+                    __bitCnt = 8;
+                }
+                byte = __MKSMALLINT(__byte);
+                bitCnt = __MKSMALLINT(__bitCnt);
+%}.
+                0
+
+"/                dT := ditherMatrix at:(x \\ dW) + (y \\ dH * dW) + 1.
+"/     
+"/                byte := byte bitShift:1.
+"/                grey < dT ifTrue:[
+"/                    byte := byte bitOr:1.
+"/                ].
+"/                bitCnt := bitCnt - 1.
+"/                bitCnt == 0 ifTrue:[
+"/                    monoBits at:dstIndex put:byte.
+"/                    dstIndex := dstIndex + 1.
+"/                    byte := 0.
+"/                    bitCnt := 8.
+"/                ].
+
+            ].
+            bitCnt ~~ 8 ifTrue:[
+                byte := byte bitShift:bitCnt.
+                monoBits at:dstIndex put:byte.
+            ].
+            dstIndex := nextDst.
+        ].
+    ].
+    ^ monoBits
+!
+
+stevensonArceDitheredMonochromeBits
+    "return the bitmap for a dithered monochrome bitmap from the image.
+     Works for any source depths / photometric"
+
+    |f last    
+     dstIndex        "{Class: SmallInteger }"
+     nextDst         "{Class: SmallInteger }"
+     bytesPerMonoRow "{Class: SmallInteger }"
+     monoBits greyValues
+     errorArray
+     errorArray1 errorArray2 errorArray3
+     e t
+     w               "{Class: SmallInteger }"
+     h               "{Class: SmallInteger }"
+     bitCnt          "{Class: SmallInteger }"
+     byte            "{Class: SmallInteger }" 
+     direction       "{Class: SmallInteger }"
+     dstClr grey dT 
+     xE              "{Class: SmallInteger }" 
+     xN              "{Class: SmallInteger }"
+     eR eRB eB eLB |
+
+    self depth > 12 ifTrue:[
+        ^ self floydSteinbergDitheredMonochromeBits
+    ].
+
+    w := width.
+    h := height.
+
+    bytesPerMonoRow := (w + 7) // 8.
+    monoBits := ByteArray uninitializedNew:(bytesPerMonoRow * h).
+    (monoBits isNil or:[bytes isNil]) ifTrue:[
+        ^ nil
+    ].
+
+    errorArray := Array new:(w+6).
+    errorArray1 := Array new:(w+6) withAll:0.
+    errorArray2 := Array new:(w+6) withAll:0.
+    errorArray3 := Array new:(w+6) withAll:0.
+
+    dstIndex := 1.
+
+    "/ fetch scaled brightness values outside of loop into a table;
+    "/ use table-value in loop
+
+    greyValues := self greyMapForRange:(255 * 1024).
+    
+    0 to:(h-1) do:[:y |
+        nextDst := dstIndex + bytesPerMonoRow.
+        byte := 0.
+        bitCnt := 8.
+
+        t := errorArray.
+        errorArray := errorArray1.
+        errorArray1 := errorArray2.
+        errorArray2 := errorArray3.
+        errorArray3 := t.
+
+        errorArray3 atAllPut:0.
+
+        self valuesAtY:y from:0 to:(w-1) do:[:x :pixel |
+            |eP eD|
+
+            "/ get the colors grey value [0 .. 1]
+            grey := greyValues at:(pixel + 1).
+
+            "/ adjust error
+            xE := x + 3 + 1.
+            grey := (grey + (errorArray at:xE)).
+
+            byte := byte bitShift:1.
+            grey > (127 * 1024) ifTrue:[
+                byte := byte bitOr:1.      "/ white
+                e := grey - (255 * 1024)
+            ] ifFalse:[
+                e := grey                  "/ black
+            ].
+
+            e ~= 0 ifTrue:[
+                "/ distribute the error:
+                "/                  XX    32
+                "/         12    26    30    16
+                "/            12    26    12
+                "/          5    12    12     5
+
+                eD := e.
+                e := e // 200.
+
+                eP := e * 32. eD := eD - eP.
+                errorArray at:xE+2 put:(errorArray at:xE+2) + eP.
+
+                eP := e * 30. eD := eD - eP.
+                errorArray1 at:xE+1 put:(errorArray1 at:xE+1) + eP.
+
+                eP := e * 16. eD := eD - eP.
+                errorArray1 at:xE+3 put:(errorArray1 at:xE+3) + eP.
+
+                eP := e * 26. eD := eD - eP.
+                errorArray1 at:xE-1 put:(errorArray1 at:xE-1) + eP.
+
+                eD := eD - eP.
+                errorArray2 at:xE put:(errorArray2 at:xE) + eP.
+
+                eP := e * 12. eD := eD - eP.
+                errorArray1 at:xE-3 put:(errorArray1 at:xE-3) + eP.
+
+                eD := eD - eP.
+                errorArray2 at:xE-2 put:(errorArray2 at:xE-2) + eP.
+
+                eD := eD - eP.
+                errorArray2 at:xE+2 put:(errorArray2 at:xE+2) + eP.
+
+                eD := eD - eP.
+                errorArray3 at:xE-1 put:(errorArray3 at:xE-1) + eP.
+
+                eD := eD - eP.
+                errorArray3 at:xE+1 put:(errorArray3 at:xE+1) + eP.
+
+                eP := e * 5. eD := eD - eP.
+                errorArray3 at:xE-3 put:(errorArray3 at:xE-3) + eP.
+
+                eP := eD.
+                errorArray3 at:xE+3 put:(errorArray3 at:xE+3) + eP.
+            ].
+
+            bitCnt := bitCnt - 1.
+            bitCnt == 0 ifTrue:[
+                monoBits at:dstIndex put:byte.
+                dstIndex := dstIndex + 1.
+                byte := 0.
+                bitCnt := 8.
+            ].
+
+        ].
+        bitCnt ~~ 8 ifTrue:[
+            byte := byte bitShift:bitCnt.
+            monoBits at:dstIndex put:byte.
+        ].
+
+        dstIndex := nextDst.
+    ].
+
+    ^ monoBits
+
+    "Created: 10.6.1996 / 12:38:35 / cg"
+    "Modified: 10.6.1996 / 12:52:20 / cg"
+! !
+
 !Image methodsFor:'enumerating'!
 
 atY:y from:x1 to:x2 do:aBlock
@@ -3549,8 +4704,8 @@
         aBlock value:xRun value:(self atX:xRun y:y)
     ]
 
-    "Modified: 7.6.1996 / 18:29:25 / cg"
     "Created: 7.6.1996 / 19:12:51 / cg"
+    "Modified: 10.6.1996 / 10:27:29 / cg"
 !
 
 colorsFromX:xStart y:yStart toX:xEnd y:yEnd do:aBlock
@@ -4448,7 +5603,9 @@
     "return a collection to map from pixelValues to greyLevels
      in the range 0..range. The brightness values are not rounded."
 
-    |d n greyMap|
+    |d r
+     n "{Class: SmallInteger }"
+     greyArray|
 
     d := self bitsPerPixel.
     n := 1 bitShift:d.
@@ -4457,26 +5614,27 @@
         ^ nil
     ].
 
-    greyMap := Array new:n.
+    greyArray := Array new:n.
 
     photometric == #palette ifTrue:[
         1 to:(colorMap size) do:[:i |
-            greyMap at:i put:(range * (colorMap at:i) brightness)
+            greyArray at:i put:(range * (colorMap at:i) brightness)
         ].
     ] ifFalse:[
         photometric == #rgb ifTrue:[
             1 to:n do:[:i |
-                greyMap at:i put:(range * (self colorFromValue:(i-1)) brightness)
+                greyArray at:i put:(range * (self colorFromValue:(i-1)) brightness)
             ]
         ] ifFalse:[
+            r := range asFloat.
             1 to:n do:[:i |
-                greyMap at:i put:(range / (n-1) * (i-1))
+                greyArray at:i put:(r / (n-1) * (i-1))
             ].
             photometric == #blackIs0 ifTrue:[
                 "/ we are done
             ] ifFalse:[
                 photometric == #whiteIs0 ifTrue:[
-                    greyMap reverse
+                    greyArray reverse
                 ] ifFalse:[
                     self error:'invalid format'.
                     ^ nil
@@ -4484,16 +5642,18 @@
             ]
         ]
     ].
-    ^ greyMap
+    ^ greyArray
 
     "
      Depth8Image new greyMapForRange:64
      Depth4Image new greyMapForRange:64
 
+     Depth16Image new greyMapForRange:1
      Depth4Image new greyMapForRange:1
-    "
-
-    "Modified: 8.6.1996 / 12:03:46 / cg"
+     Depth2Image new greyMapForRange:1
+    "
+
+    "Modified: 10.6.1996 / 10:37:40 / cg"
 !
 
 magnifyRowFrom:srcBytes offset:srcStart pixels:oldPixels 
@@ -4568,6 +5728,7 @@
         "/ assume that the red bits are the leftMost bits
 
         blueBits := bitsPerSample at:3.
+        blueBits == 0 ifTrue:[^ 0].
 
         ^ pixel bitAnd:(1 bitShift:blueBits)-1
     ].
@@ -4575,7 +5736,7 @@
     self subclassResponsibility
 
     "Created: 8.6.1996 / 09:44:21 / cg"
-    "Modified: 8.6.1996 / 09:51:45 / cg"
+    "Modified: 10.6.1996 / 14:59:44 / cg"
 !
 
 blueComponentOf:pixel
@@ -4589,6 +5750,8 @@
         "/ assume that the red bits are the leftMost bits
 
         blueBits := bitsPerSample at:3.
+        blueBits == 0 ifTrue:[^ 0].
+
         s := (1 bitShift:blueBits) - 1.
 
         ^ 100.0 / s * (pixel bitAnd:(1 bitShift:blueBits)-1)
@@ -4597,7 +5760,7 @@
     self subclassResponsibility
 
     "Created: 8.6.1996 / 08:45:22 / cg"
-    "Modified: 8.6.1996 / 09:51:40 / cg"
+    "Modified: 10.6.1996 / 14:55:39 / cg"
 !
 
 bounds
@@ -4676,6 +5839,7 @@
         "/ assume that the red bits are the leftMost bits
 
         greenBits := bitsPerSample at:2.
+        greenBits == 0 ifTrue:[^ 0].
         blueBits := bitsPerSample at:3.
 
         ^ (pixel bitShift:blueBits negated) bitAnd:(1 bitShift:greenBits)-1
@@ -4683,8 +5847,8 @@
 
     self subclassResponsibility
 
-    "Modified: 8.6.1996 / 08:56:00 / cg"
     "Created: 8.6.1996 / 09:44:37 / cg"
+    "Modified: 10.6.1996 / 14:59:35 / cg"
 !
 
 greenComponentOf:pixel
@@ -4698,6 +5862,7 @@
         "/ assume that the red bits are the leftMost bits
 
         greenBits := bitsPerSample at:2.
+        greenBits == 0 ifTrue:[^ 0].
         blueBits := bitsPerSample at:3.
 
         s := (1 bitShift:greenBits) - 1.
@@ -4708,7 +5873,7 @@
     self subclassResponsibility
 
     "Created: 8.6.1996 / 08:45:34 / cg"
-    "Modified: 8.6.1996 / 09:47:12 / cg"
+    "Modified: 10.6.1996 / 14:55:24 / cg"
 !
 
 heightOn:aGC
@@ -4747,6 +5912,7 @@
         "/ assume that the red bits are the leftMost bits
 
         redBits := bitsPerSample at:1.
+        redBits == 0 ifTrue:[^ 0].
         greenBits := bitsPerSample at:2.
         blueBits := bitsPerSample at:3.
 
@@ -4757,7 +5923,7 @@
     self subclassResponsibility
 
     "Created: 8.6.1996 / 09:44:51 / cg"
-    "Modified: 8.6.1996 / 09:50:59 / cg"
+    "Modified: 10.6.1996 / 14:59:05 / cg"
 !
 
 redComponentOf:pixel
@@ -4771,6 +5937,8 @@
         "/ assume that the red bits are the leftMost bits
 
         redBits := bitsPerSample at:1.
+        redBits == 0 ifTrue:[^ 0].
+
         greenBits := bitsPerSample at:2.
         blueBits := bitsPerSample at:3.
 
@@ -4784,7 +5952,7 @@
     self subclassResponsibility
 
     "Created: 8.6.1996 / 08:45:30 / cg"
-    "Modified: 8.6.1996 / 09:51:29 / cg"
+    "Modified: 10.6.1996 / 14:57:24 / cg"
 !
 
 usedColors
@@ -5175,6 +6343,6 @@
 !Image class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.84 1996-06-08 13:35:52 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/Image.st,v 1.85 1996-06-10 13:21:51 cg Exp $'
 ! !
 Image initialize!