Changeset 1930


Ignore:
Timestamp:
11/11/07 13:27:40 (6 years ago)
Author:
sam
Message:
  • Introducing dither matrices.
Location:
www/study
Files:
13 added
5 edited

Legend:

Unmodified
Added
Removed
  • www/study/index.html

    r1926 r1930  
    4040  <img src="lenna256bw.png" width="256" height="256" 
    4141       class="inline" alt="Lenna (256x256BW)" /> 
     42  <img src="gradient256bw.png" width="32" height="256" 
     43       class="inline" alt="gradient" /> 
    4244</p> 
    4345 
     
    106108</p> 
    107109 
    108 <p> Still not very good. Obviously something better is needed. </p> 
     110<p> Choosing the best thresholding value for a given image is called 
     111<b>average dithering</b>. But even with the best value, the results will 
     112not improve tremendously. </p> 
    109113 
    110114<h3> 1.2. Grayscale thresholding </h3> 
     
    172176</p> 
    173177 
    174 <!--<p> Even if the shades --> 
    175  
    176 <h3> 2.3. Introducing gamma </h3> 
    177  
    178 <p> More importantly, if you are reading this document on a computer 
     178<p> Obviously the middle pattern looks far better to the human eye on a 
     179computer screen. Optimising patterns so that they look good to the human 
     180eye and don't create artifacts is a crucial element of a dithering 
     181algorithm. Here is another example of two patterns that approximate to 
     182the same shade of gray but may look slightly different from a distance: </p> 
     183 
     184<p style="text-align: center;"> 
     185  <img src="pat004.png" width="320" height="80" 
     186       class="inline" alt="two different 25% patterns" /> 
     187</p> 
     188 
     189<h3> 2.3. Ordered dither </h3> 
     190 
     191<p> A generalisation of the dithering technique we just saw that uses a 
     192certain family of patterns is called <b>ordered dither</b>. It is based on 
     193a <b>dither matrix</b> such as the following one: </p> 
     194 
     195<p style="text-align: center;"> 
     196  <img src="fig001.png" width="128" height="128" alt="2x2 dither matrix" /> 
     197</p> 
     198 
     199<p> This matrix is then repeated all over the image, and the cells are used 
     200as threshold values. In this case, pixels (0,0), (0,2), (0,4) etc. will be 
     201thresholded with a value of 0.2. Pixels (0,1), (0, 3), (0, 4) etc. will be 
     202thresholded with a value of 0.8, and so on, resulting in the image seen 
     203in 2.1. </p> 
     204 
     205<p> Different matrices can give very different results. This is a 4×4 
     206Bayer ordered dither matrix: </p> 
     207 
     208<p style="text-align: center;"> 
     209  <img src="fig002.png" width="160" height="160" 
     210       style="margin-right: 30px;" alt="4x4 Bayer matrix" /> 
     211  <img src="out007.png" width="256" height="256" 
     212       class="inline" alt="4x4 Bayer dithering" /> 
     213  <img src="grad007.png" width="32" height="256" 
     214       class="inline" alt="4x4 Bayer dithering gradient" /> 
     215</p> 
     216 
     217<p> This 4×4 cluster dot matrix creates dot patterns that mimic the 
     218halftoning techniques used by newspapers: </p> 
     219 
     220<p style="text-align: center;"> 
     221  <img src="fig003.png" width="160" height="160" 
     222       style="margin-right: 30px;" alt="4x4 cluster dot matrix" /> 
     223  <img src="out008.png" width="256" height="256" 
     224       class="inline" alt="4x4 cluster dot dithering" /> 
     225  <img src="grad008.png" width="32" height="256" 
     226       class="inline" alt="4x4 cluster dot dithering gradient" /> 
     227</p> 
     228 
     229<p> This unusual 5×3 matrix creates artistic vertical line artifacts: </p> 
     230 
     231<p style="text-align: center;"> 
     232  <img src="fig004.png" width="200" height="120" 
     233       style="margin-right: 30px;" alt="4x4 cluster dot matrix" /> 
     234  <img src="out009.png" width="256" height="256" 
     235       class="inline" alt="4x4 cluster dot dithering" /> 
     236  <img src="grad009.png" width="32" height="256" 
     237       class="inline" alt="4x4 cluster dot dithering gradient" /> 
     238</p> 
     239 
     240<!-- 
     241<h3> 3. Introducing gamma </h3> 
     242 
     243<p> If you are reading this document on a computer 
    179244screen, you may have noticed that the above 50% pattern was closer to a 0.73 
    180245grayscale (left) than to the intuitively expected 0.5 value (right). If you 
     
    195260 
    196261<p style="text-align: center;"> 
    197   <img src="fig001.png" width="256" height="230" alt="introducing gamma" /> 
     262  <img src="fig001.png" width="300" height="240" alt="introducing gamma" /> 
    198263</p> 
    199264 
     
    227292  <img src="grad007.png" width="32" height="256" 
    228293       class="inline" alt="gamma-aware 3-pattern halftoning gradient" /> 
    229   <img src="out008.png" width="32" height="256" 
    230        class="inline" alt="gamma-aware 6.25%, 25% and 50% halftoning" /> 
    231 </p> 
     294</p> 
     295--> 
    232296 
    233297<!-- 
     298<h3> Gamma with more gray levels </h3> 
     299 
     300<p> As seen above, the smoothest dithering pattern that can be created with 
     301black and white is by uniformly alterning the two colours. However, the 
     302resulting colour (0.73) it is not evenly situated on the gray scale. </p> 
     303 
    234304  <img src="out008.png" width="256" height="256" 
    235305       class="inline" alt="gamma-aware 6.25%, 25% and 50% halftoning" /> 
  • www/study/study.py

    r1927 r1930  
    4747    for y in range(256): 
    4848        gradient256bw.setGray(x, 255 - y, y / 255.) 
     49gradient256bw.writePng("gradient256bw.png") 
    4950 
    5051# Output 1: 50% threshold 
     
    143144        dest.setGray(x, y, c) 
    144145dest.writePng("pat003.png") 
     146 
     147# Pattern 4: two different 25% patterns 
     148dest = Image((320, 80)) 
     149for y in range(80): 
     150    for x in range(80): 
     151        c = (x / 2 & 1) and (y / 2 & 1) 
     152        dest.setGray(x, y, c) 
     153    for x in range(80, 160): 
     154        c = (x & 1) and (y & 1) 
     155        dest.setGray(x, y, c) 
     156    for x in range(160, 240): 
     157        c = (x & 1) and ((y + x / 2) & 1) 
     158        dest.setGray(x, y, c) 
     159    for x in range(240, 320): 
     160        c = (x / 2 & 1) and ((y / 2 + x / 4) & 1) 
     161        dest.setGray(x, y, c) 
     162dest.writePng("pat004.png") 
     163 
     164# Output 7: 4x4 Bayer dithering 
     165def test4(src, mat, name): 
     166    (w, h) = src.size() 
     167    dest = Image((w, h)) 
     168    dx = len(mat[0]) 
     169    dy = len(mat) 
     170    for y in range(h): 
     171        for x in range(w): 
     172            c = src.getGray(x, y) 
     173            threshold = (1. + mat[y % dy][x % dx]) / (dx * dy + 1) 
     174            c = c > threshold 
     175            dest.setGray(x, y, c) 
     176    dest.writePng(name) 
     177 
     178mat = [[  0,  8,  3, 11], 
     179       [ 15,  4, 12,  7], 
     180       [  2, 10,  1,  9], 
     181       [ 13,  6, 14,  5]] 
     182test4(lenna256bw, mat, "out007.png") 
     183test4(gradient256bw, mat, "grad007.png") 
     184 
     185mat = [[ 12,  5,  6, 13], 
     186       [  4,  0,  1,  7], 
     187       [ 11,  3,  2,  8], 
     188       [ 15, 10,  9, 14]] 
     189test4(lenna256bw, mat, "out008.png") 
     190test4(gradient256bw, mat, "grad008.png") 
     191 
     192mat = [[ 13,  7,  0,  4, 10], 
     193       [  9,  3,  1,  8, 14], 
     194       [ 11,  5,  2,  6, 12],] 
     195test4(lenna256bw, mat, "out009.png") 
     196test4(gradient256bw, mat, "grad009.png") 
     197 
     198############################################################################## 
     199# Only temporary cruft below this 
     200import sys 
     201sys.exit(0) 
     202 
     203 
     204 
    145205 
    146206# Pattern 4: gamma-corrected 50% gray, black-white halftone, 50% gray 
     
    213273 
    214274 
    215 ############################################################################## 
    216 # Only temporary cruft below this 
    217  
    218275src = lenna256bw 
    219276src = gradient256bw 
     
    224281       [  2, 10,  1,  9], 
    225282       [ 13,  6, 14,  5]] 
    226 mat = [[  6,  7,  8,  9], 
    227        [  5,  0,  1, 10], 
    228        [  4,  3,  2, 11], 
    229        [ 15, 14, 13, 12]] 
    230 mat = [[ 12,  5,  9, 13], 
    231        [  8,  0,  1,  6], 
    232        [  4,  3,  2, 10], 
    233        [ 15, 11,  7, 14]] 
    234 mat = [[ 35, 24, 13, 14, 25, 32], 
    235        [ 31, 12,  5,  6, 15, 26], 
    236        [ 23,  4,  0,  1,  7, 16], 
    237        [ 22, 11,  3,  2,  8, 17], 
    238        [ 30, 21, 10,  9, 18, 27], 
    239        [ 34, 29, 20, 19, 28, 33]] 
    240 mat = [[  0, 20, 30,  3, 23, 29], 
    241        [ 12, 32, 18, 15, 35, 17], 
    242        [ 27,  8,  4, 24, 11,  7], 
    243        [  2, 22, 28,  1, 21, 31], 
    244        [ 14, 34, 16, 13, 33, 19], 
    245        [ 25, 10,  6, 26,  9,  5]] 
     283#mat = [[  6,  7,  8,  9], 
     284#       [  5,  0,  1, 10], 
     285#       [  4,  3,  2, 11], 
     286#       [ 15, 14, 13, 12]] 
     287#mat = [[ 12,  5,  9, 13], 
     288#       [  8,  0,  1,  6], 
     289#       [  4,  3,  2, 10], 
     290#       [ 15, 11,  7, 14]] 
     291size = 4 
     292#mat = [[ 35, 24, 13, 14, 25, 32], 
     293#       [ 31, 12,  5,  6, 15, 26], 
     294#       [ 23,  4,  0,  1,  7, 16], 
     295#       [ 22, 11,  3,  2,  8, 17], 
     296#       [ 30, 21, 10,  9, 18, 27], 
     297#       [ 34, 29, 20, 19, 28, 33]] 
     298#mat = [[  0, 20, 30,  3, 23, 29], 
     299#       [ 12, 32, 18, 15, 35, 17], 
     300#       [ 27,  8,  4, 24, 11,  7], 
     301#       [  2, 22, 28,  1, 21, 31], 
     302#       [ 14, 34, 16, 13, 33, 19], 
     303#       [ 25, 10,  6, 26,  9,  5]] 
     304#size = 6 
    246305dest = Image((w, h)) 
    247306for y in range(h): 
     
    249308        c = src.getGray(x, y) 
    250309        i = Gamma.CtoI(c) 
    251         threshold = mat[x % 6][y % 6] 
    252         c = math.floor(i * 35.999) > threshold 
     310        threshold = mat[x % size][y % size] 
     311        d = math.floor(i * (size * size + .9999)) > threshold 
     312        if c > 0.95: 
     313            print c, i, i * (size * size + .9999) 
     314        c = d 
    253315        dest.setGray(x, y, c) 
    254316dest.writePng("out008.png") 
    255  
    256 import sys 
    257 sys.exit(0) 
    258317 
    259318# Create a dot-matrix pattern 
Note: See TracChangeset for help on using the changeset viewer.