- encoded as colorized black-white image (5 kB)
- 1:1 copy of a small image (20 kB)
- picture with 3 colors encoded and resized as colorized black-white image (26 kB)
- picture of the author in colored high quality mode (101 kB)
- copy encodeded colored with same size as original but lower resolution (137 kB)

a) original lena image |
b) halftoning by ordered dither with a 2x2 pattern |
---|---|

c) halftoning along a fractal path |
d) halftoning along a fractal path with corrected greyvalues |

e) halftoning by ordered dither with transition smoothing larger image as pure HTML (zipped 32kB) |
f) halftoning by ordered dither with pattern orientation by hilbert curve and transition smoothing larger image as pure HTML (zipped 53kB) |

original grey scale ramp image |
halftoning by algorithm used in image b) |

halftoning by algorithm used in image c) |
halftoning by algorithm used in image d) |

halftoning by algorithm used in image e) |
halftoning by algorithm used in image f) |

Dim ccStrP, ccStr0, ccStr1 Dim ccStr(4) ccStrP = Array("II", "I.", "I ", ". ", " ") ccStr0 = Array("II", "I'", ".'", ". ", " ") ccStr1 = Array("II", "I.", "'.", "' ", " ") ccStr(0) = Array("II", "I.", "I ", "' ", " ") ccStr(1) = Array("II", "'I", "''", "' ", " ") ccStr(2) = Array("II", "'I", " I", " .", " ") ccStr(3) = Array("II", "I.", "..", " .", " ") '...some lines have been erased here cc = (2 * rr + 3 * gg + bb) 'used weights for red green and blue Select Case BWEncoding Case 0: '-----------SEE IMAGE b)------------------ cc = cc \ 308 'cc=0, 1, 2, 3, 4 iiHTML = iiHTML & ccStrP(cc) Case 1: '-----------SEE IMAGE e)------------------ cc = cc + ((xx + yy) Mod 2) * 192 - 96 'smoothing If cc < 0 Then cc = 0 cc = cc \ 308 'cc=0, 1, 2, 3, 4 If cc > 4 Then cc = 4 If (xx + yy) Mod 2 = 0 Then iiHTML = iiHTML & ccStr0(cc) Else iiHTML = iiHTML & ccStr1(cc) End If Case 2: '-----------SEE IMAGE f)------------------ cc = cc + ((xx + yy) Mod 2) * 192 - 96 'smoothing If cc < 0 Then cc = 0 cc = cc \ 308 'c=0, 1, 2, 3, 4 If cc > 4 Then cc = 4 hh_Shape = GetHilbertShape(xx, yy) iiHTML = iiHTML & ccStr(hh_Shape)(cc) End Select 'The function GetHilbertshape(i, j) returns 0, 1, 2 or 3, which represents the 'orientation of a hilbert curve of a size 2^(2*n) at pixel position (i, j) 'see code below: ------------------------------------------------------------------ Function GetHilbertShape(aii As Integer, ajj As Integer) As Integer Dim ss, ii, jj ii = 4 * aii + ajj 'coordinate trafo to get rid of artifacts jj = 4 * ajj + aii 'try out other combinations too! ss = 1 While ((ii >= ss) Or (jj >= ss)) ss = ss * 4 Wend GetHilbertShape = GetHilbertShapeEven(ii, jj, ss, 0) 'GetHilbertShape = Int((4 * Rnd)) 'check out a random distribution End Function ------------------------------------------------------------------ Function GetHilbertShapeEven(ByVal axx As Integer, ByVal ayy As Integer, ByVal asize As Integer, ByVal arot As Integer) As Integer If asize = 1 Then GetHilbertShapeEven = arot Mod 4 Exit Function End If Dim xx, yy, size2, rot xx = axx: yy = ayy: size2 = asize \ 2: rot = arot If (yy < size2) Then If (xx < size2) Then GetHilbertShapeEven = GetHilbertShapeOdd(xx, yy, size2, rot) Else GetHilbertShapeEven = GetHilbertShapeOdd(2 * size2 - 1 - xx, size2 - 1 - yy, size2, rot + 2) End If Else If (xx < size2) Then GetHilbertShapeEven = GetHilbertShapeOdd(yy - size2, size2 - 1 - xx, size2, rot + 3) Else GetHilbertShapeEven = GetHilbertShapeOdd(yy - size2, 2 * size2 - 1 - xx, size2, rot + 3) End If End If End Function ---------------------------------------------------------------------- Function GetHilbertShapeOdd(ByVal axx As Integer, ByVal ayy As Integer, ByVal asize As Integer, ByVal arot As Integer) As Integer Dim xx, yy, size2, rot xx = axx: yy = ayy: size2 = asize / 2: rot = arot If (yy < size2) Then If (xx < size2) Then GetHilbertShapeOdd = GetHilbertShapeEven(xx, yy, size2, rot) Else GetHilbertShapeOdd = GetHilbertShapeEven(size2 - 1 - yy, xx - size2, size2, rot + 1) End If Else If (xx < size2) Then GetHilbertShapeOdd = GetHilbertShapeEven(size2 - 1 - xx, 2 * size2 - 1 - yy, size2, rot + 2) Else GetHilbertShapeOdd = GetHilbertShapeEven(2 * size2 - 1 - yy, xx - size2, size2, rot + 1) End If End If End Function

The Images c) and d) have been generated by walking on this fractal spacefilling curve and applying the following halftoning algorithm: |
---|

Sub DitherFract(ByVal i As Integer, ByVal j As Integer) Dim rr As Integer Dim gg As Integer Dim bb As Integer Dim cc As Long ' Dim cc_128 As Long ' Dim cc_min As Long ' cc_128 = 160 ' cc_min = 10 If ((i <= imax) And (j <= jmax)) Then cc = Pic.Point(i, j) Long2RGB cc, rr, gg, bb cc = (2 * rr + 3 * gg + bb) \ 6 ' If cc <= cc_128 Then ' cc = cc * (110 - cc_min) \ cc_128 + cc_min ' Else ' cc = (cc - cc_128) * (255 - 146) \ (255 - cc_128) + 146 ' End If cc = cc - 128 DitherError = DitherError + CInt(cc) * 32 \ 31 If DitherErro <= 0 Then Pic.PSet (i, j), RGB(0, 0, 0) DitherError = DitherError + 128 Else Pic.PSet (i, j), RGB(255, 255, 255) DitherError = DitherError - (255 - 128) End If End If DitherError = DitherError * 31 \ 32 End Sub

color error minimal f=1 |
intermediate f=3/4 |
spatial error minimal f=0 |

compare with alg. e) (44kB) and alg. f) (56kB) (both as pure HTML pictures) |

avg. distance when walking | 1 Pixel | 2 Pixel | 3 Pixel | 4 Pixel | |
---|---|---|---|---|---|

1: 1/1 avg: 1 | 2: 1/1 avg: 2 | 3: 1/1 avg: 3 | 4: 1/1 avg: 4 | LOSER | |

1: 1/1 avg: 1 | sqrt(2): 2/3 2: 1/3 avg: 1.61 | 1: 6/27 sqrt(5): 20/27 3: 1/27 avg: 1.99 | sqrt(2): 5/27 2: 12/27 sqrt(8): 7/27 sqrt(10): 3/27 avg: 2.23 | second winner | |

1: 1/1 avg: 1 | sqrt(2): 4/5 2: 1/5 avg: 1.53 | 1: 19/60 sqrt(5): 40/60 3: 1/60 avg: 1.86 | sqrt(2): 1/5 2: 3/5 sqrt(10): 1/5 avg: 2.12 | WINNER |

There is also a method for generating a spacefilling curve of arbitrary size.