Changeset 2029
- Timestamp:
- Nov 19, 2007, 1:40:43 AM (13 years ago)
- Location:
- www/study
- Files:
-
- 1 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
www/study/index.html
r2027 r2029 68 68 the <tt><a href="study.py">study.py</a></tt> Python program. Just install 69 69 the <tt>python-gd</tt> package on your favourite operating system and 70 run the script. The original Lenna images were generated with the71 <tt><a href="lenna.py">lenna.py</a></tt> program from the original colour 72 512×512 image. </p>70 run the script. The different Lenna images were generated with the same 71 script from the <a href="http://www.cs.cmu.edu/~chuck/lennapg/">original 72 colour 512×512 image</a>. </p> 73 73 74 74 <h3> Sections </h3> -
www/study/study.py
r2028 r2029 1 1 #!/usr/bin/env python 2 2 3 import math, gd, random 3 import math, gd, random, sys 4 5 # Select which chapters to run 6 def chapter(n): 7 if len(sys.argv) == 1: 8 return True 9 return str(n) in sys.argv 10 11 ############################################################################## 4 12 5 13 # Tiny image class to make examples short and readable 6 14 class Image(gd.image): 7 def __ new__(args, truecolor = False):15 def __init__(self, *args): 8 16 gd.gdMaxColors = 256 * 256 * 256 9 if truecolor: 10 return gd.image.__new__(args, True) 11 else: 12 return gd.image.__new__(args) 17 if args[0].__class__ == str: 18 print " * loading %s" % (args[0],) 19 gd.image.__init__(self, *args) 13 20 def save(self, name): 14 21 print " * saving %s" % (name,) … … 33 40 self.setPixel((x, y), c) 34 41 35 ##############################################################################36 print "Initialisation"37 38 42 # Manipulate gamma values 39 43 class Gamma: … … 46 50 CtoI = staticmethod(CtoI) 47 51 ItoC = staticmethod(ItoC) 48 49 # Load the 256x256 grayscale Lenna image 50 lenna256bw = Image("lenna256bw.png") 52 def Cto2(x): 53 if x < Gamma.CtoI(0.50): 54 return 0. 55 return 1. 56 def Cto3(x): 57 if x < Gamma.CtoI(0.25): 58 return 0. 59 elif x < Gamma.CtoI(0.75): 60 return Gamma.CtoI(0.5) 61 return 1. 62 def Cto4(x): 63 if x < Gamma.CtoI(0.17): 64 return 0. 65 elif x < Gamma.CtoI(0.50): 66 return Gamma.CtoI(0.3333) 67 elif x < Gamma.CtoI(0.83): 68 return Gamma.CtoI(0.6666) 69 return 1. 70 Cto2 = staticmethod(Cto2) 71 Cto3 = staticmethod(Cto3) 72 Cto4 = staticmethod(Cto4) 73 74 ############################################################################## 75 print "Initialisation" 76 77 # Load the original Lenna image 78 lenna512 = Image("lenna512.png") 79 (w, h) = lenna512.size() 80 81 # Image 1: grayscale conversion 82 # Read the compression FAQ [55] for the rationale behind using the green 83 # channel (http://www.faqs.org/faqs/compression-faq/part1/section-30.html) 84 if chapter(0): 85 (w, h) = lenna512.size() 86 lenna512bw = Image((w, h)) 87 for y in range(h): 88 for x in range(w): 89 rgb = lenna512.getRgb(x, y) 90 c = rgb[1] 91 lenna512bw.setGray(x, y, c) 92 lenna512bw.save("lenna512bw.png") 93 else: 94 lenna512bw = Image("lenna512bw.png") 95 96 # Image 2: 50% grayscale 97 # Image 3: 50% scaling 98 if chapter(0): 99 (w, h) = lenna512.size() 100 lenna256bw = Image((w / 2, h / 2)) 101 lenna256 = Image((w / 2, h / 2), True) 102 for y in range(h / 2): 103 for x in range(w / 2): 104 r = g = b = 0. 105 for j in range(2): 106 for i in range(2): 107 rgb = lenna512.getRgb(x * 2 + i, y * 2 + j) 108 r += Gamma.CtoI(rgb[0]) 109 g += Gamma.CtoI(rgb[1]) 110 b += Gamma.CtoI(rgb[2]) 111 r = Gamma.ItoC(r / 4) 112 g = Gamma.ItoC(g / 4) 113 b = Gamma.ItoC(b / 4) 114 lenna256bw.setGray(x, y, g) 115 lenna256.setRgb(x, y, r, g, b) 116 lenna256bw.save("lenna256bw.png") 117 lenna256.save("lenna256.png") 118 else: 119 lenna256bw = Image("lenna256bw.png") 120 lenna256 = Image("lenna256.png") 51 121 52 122 # Create a 32x256 grayscale gradient 53 gradient256bw = Image((32, 256)) 54 for x in range(32): 55 for y in range(256): 56 gradient256bw.setGray(x, 255 - y, y / 255.) 57 gradient256bw.save("gradient256bw.png") 123 if chapter(0): 124 gradient256bw = Image((32, 256)) 125 for x in range(32): 126 for y in range(256): 127 gradient256bw.setGray(x, 255 - y, y / 255.) 128 gradient256bw.save("gradient256bw.png") 129 else: 130 gradient256bw = Image("gradient256bw.png") 58 131 59 132 ############################################################################## 60 print "Chapter 1. Colour quantisation" 133 if chapter(1): 134 print "Chapter 1. Colour quantisation" 61 135 62 136 # Output 1.1.1: 50% threshold … … 72 146 return dest 73 147 74 test11x(lenna256bw, 0.5).save("out1-1-1.png") 75 test11x(lenna256bw, 0.4).save("out1-1-2.png") 76 test11x(lenna256bw, 0.6).save("out1-1-3.png") 77 test11x(gradient256bw, 0.5).save("grad1-1-1.png") 78 test11x(gradient256bw, 0.4).save("grad1-1-2.png") 79 test11x(gradient256bw, 0.6).save("grad1-1-3.png") 148 if chapter(1): 149 test11x(lenna256bw, 0.5).save("out1-1-1.png") 150 test11x(lenna256bw, 0.4).save("out1-1-2.png") 151 test11x(lenna256bw, 0.6).save("out1-1-3.png") 152 test11x(gradient256bw, 0.5).save("grad1-1-1.png") 153 test11x(gradient256bw, 0.4).save("grad1-1-2.png") 154 test11x(gradient256bw, 0.6).save("grad1-1-3.png") 80 155 81 156 # Output 1.2.1: 3-colour threshold … … 93 168 return dest 94 169 95 test12x(lenna256bw, 3).save("out1-2-1.png") 96 test12x(lenna256bw, 5).save("out1-2-2.png") 97 test12x(gradient256bw, 3).save("grad1-2-1.png") 98 test12x(gradient256bw, 5).save("grad1-2-2.png") 170 if chapter(1): 171 test12x(lenna256bw, 3).save("out1-2-1.png") 172 test12x(lenna256bw, 5).save("out1-2-2.png") 173 test12x(gradient256bw, 3).save("grad1-2-1.png") 174 test12x(gradient256bw, 5).save("grad1-2-2.png") 99 175 100 176 # Output 1.2.3: 3-colour threshold, minimal error … … 112 188 return dest 113 189 114 test12y(lenna256bw, 3).save("out1-2-3.png") 115 test12y(lenna256bw, 5).save("out1-2-4.png") 116 test12y(gradient256bw, 3).save("grad1-2-3.png") 117 test12y(gradient256bw, 5).save("grad1-2-4.png") 190 if chapter(1): 191 test12y(lenna256bw, 3).save("out1-2-3.png") 192 test12y(lenna256bw, 5).save("out1-2-4.png") 193 test12y(gradient256bw, 3).save("grad1-2-3.png") 194 test12y(gradient256bw, 5).save("grad1-2-4.png") 118 195 119 196 ############################################################################## 120 print "Chapter 2. Halftoning patterns" 197 if chapter(2): 198 print "Chapter 2. Halftoning patterns" 121 199 122 200 # Pattern 2.1.1: a 50% halftone pattern with various block sizes 123 dest = Image((320, 80))124 for x in range(320):125 d = 8 >> (x / 80)126 for y in range(80):127 c = (x / d + y / d) & 1128 dest.setGray(x, y, c)129 dest.save("pat2-1-1.png")130 131 201 # Pattern 2.1.2: 25% and 75% halftone patterns with various block sizes 132 dest = Image((320, 80)) 133 for x in range(320): 134 d = 8 >> (x / 80) 135 for y in range(40): 136 c = ((x / d + y / d) & 1) or (y / d & 1) 137 dest.setGray(x, y, c) 138 for y in range(40, 80): 139 c = ((x / d + y / d) & 1) and (y / d & 1) 140 dest.setGray(x, y, c) 141 dest.save("pat2-1-2.png") 202 if chapter(2): 203 dest = Image((320, 80)) 204 for x in range(320): 205 d = 8 >> (x / 80) 206 for y in range(80): 207 c = (x / d + y / d) & 1 208 dest.setGray(x, y, c) 209 dest.save("pat2-1-1.png") 210 211 dest = Image((320, 80)) 212 for x in range(320): 213 d = 8 >> (x / 80) 214 for y in range(40): 215 c = ((x / d + y / d) & 1) or (y / d & 1) 216 dest.setGray(x, y, c) 217 for y in range(40, 80): 218 c = ((x / d + y / d) & 1) and (y / d & 1) 219 dest.setGray(x, y, c) 220 dest.save("pat2-1-2.png") 142 221 143 222 # Output 2.1.1: 20/40/60/80% threshold with 25/50/75% patterns inbetween: … … 161 240 return dest 162 241 163 test211(lenna256bw).save("out2-1-1.png") 164 test211(gradient256bw).save("grad2-1-1.png") 242 if chapter(2): 243 test211(lenna256bw).save("out2-1-1.png") 244 test211(gradient256bw).save("grad2-1-1.png") 165 245 166 246 # Pattern 2.2.1: vertical, mixed and horizontal black-white halftones 167 dest = Image((240, 80))168 for y in range(80):169 for x in range(80):170 c = x & 1171 dest.setGray(x, y, c)172 for x in range(80, 160):173 c = (x / d + y / d) & 1174 dest.setGray(x, y, c)175 for x in range(160, 240):176 c = y & 1177 dest.setGray(x, y, c)178 dest.save("pat2-2-1.png")179 180 247 # Pattern 2.2.2: two different 25% patterns 181 dest = Image((320, 80)) 182 for y in range(80): 183 for x in range(80): 184 c = (x / 2 & 1) and (y / 2 & 1) 185 dest.setGray(x, y, c) 186 for x in range(80, 160): 187 c = (x & 1) and (y & 1) 188 dest.setGray(x, y, c) 189 for x in range(160, 240): 190 c = (x & 1) and ((y + x / 2) & 1) 191 dest.setGray(x, y, c) 192 for x in range(240, 320): 193 c = (x / 2 & 1) and ((y / 2 + x / 4) & 1) 194 dest.setGray(x, y, c) 195 dest.save("pat2-2-2.png") 248 if chapter(2): 249 dest = Image((240, 80)) 250 for y in range(80): 251 for x in range(80): 252 c = x & 1 253 dest.setGray(x, y, c) 254 for x in range(80, 160): 255 c = (x / d + y / d) & 1 256 dest.setGray(x, y, c) 257 for x in range(160, 240): 258 c = y & 1 259 dest.setGray(x, y, c) 260 dest.save("pat2-2-1.png") 261 262 dest = Image((320, 80)) 263 for y in range(80): 264 for x in range(80): 265 c = (x / 2 & 1) and (y / 2 & 1) 266 dest.setGray(x, y, c) 267 for x in range(80, 160): 268 c = (x & 1) and (y & 1) 269 dest.setGray(x, y, c) 270 for x in range(160, 240): 271 c = (x & 1) and ((y + x / 2) & 1) 272 dest.setGray(x, y, c) 273 for x in range(240, 320): 274 c = (x / 2 & 1) and ((y / 2 + x / 4) & 1) 275 dest.setGray(x, y, c) 276 dest.save("pat2-2-2.png") 196 277 197 278 # Output 2.3.1: 4x4 Bayer dithering 198 279 # Output 2.3.2: 4x4 cluster dot 199 280 # Output 2.3.3: 5x3 line dithering 281 def test23x(src, mat): 282 (w, h) = src.size() 283 dest = Image((w, h)) 284 dx = len(mat[0]) 285 dy = len(mat) 286 for y in range(h): 287 for x in range(w): 288 c = src.getGray(x, y) 289 threshold = (1. + mat[y % dy][x % dx]) / (dx * dy + 1) 290 c = c > threshold 291 dest.setGray(x, y, c) 292 return dest 293 200 294 DITHER_BAYER44 = \ 201 295 [[ 0, 12, 3, 15], … … 231 325 [ 11, 5, 2, 6, 12],] 232 326 233 def test23x(src, mat): 234 (w, h) = src.size() 235 dest = Image((w, h)) 236 dx = len(mat[0]) 237 dy = len(mat) 238 for y in range(h): 239 for x in range(w): 240 c = src.getGray(x, y) 241 threshold = (1. + mat[y % dy][x % dx]) / (dx * dy + 1) 242 c = c > threshold 243 dest.setGray(x, y, c) 244 return dest 245 246 test23x(lenna256bw, DITHER_BAYER44).save("out2-3-1.png") 247 test23x(gradient256bw, DITHER_BAYER44).save("grad2-3-1.png") 248 249 test23x(lenna256bw, DITHER_BAYER88).save("out2-3-1b.png") 250 test23x(gradient256bw, DITHER_BAYER88).save("grad2-3-1b.png") 251 252 test23x(lenna256bw, DITHER_CLUSTER44).save("out2-3-2.png") 253 test23x(gradient256bw, DITHER_CLUSTER44).save("grad2-3-2.png") 254 255 test23x(lenna256bw, DITHER_CLUSTER88).save("out2-3-2b.png") 256 test23x(gradient256bw, DITHER_CLUSTER88).save("grad2-3-2b.png") 257 258 test23x(lenna256bw, DITHER_LINE53).save("out2-3-3.png") 259 test23x(gradient256bw, DITHER_LINE53).save("grad2-3-3.png") 327 if chapter(2): 328 test23x(lenna256bw, DITHER_BAYER44).save("out2-3-1.png") 329 test23x(gradient256bw, DITHER_BAYER44).save("grad2-3-1.png") 330 331 test23x(lenna256bw, DITHER_BAYER88).save("out2-3-1b.png") 332 test23x(gradient256bw, DITHER_BAYER88).save("grad2-3-1b.png") 333 334 test23x(lenna256bw, DITHER_CLUSTER44).save("out2-3-2.png") 335 test23x(gradient256bw, DITHER_CLUSTER44).save("grad2-3-2.png") 336 337 test23x(lenna256bw, DITHER_CLUSTER88).save("out2-3-2b.png") 338 test23x(gradient256bw, DITHER_CLUSTER88).save("grad2-3-2b.png") 339 340 test23x(lenna256bw, DITHER_LINE53).save("out2-3-3.png") 341 test23x(gradient256bw, DITHER_LINE53).save("grad2-3-3.png") 260 342 261 343 # Output 2.4.1: uniform random dithering … … 271 353 return dest 272 354 273 test241(lenna256bw).save("out2-4-1.png") 274 test241(gradient256bw).save("grad2-4-1.png") 355 if chapter(2): 356 test241(lenna256bw).save("out2-4-1.png") 357 test241(gradient256bw).save("grad2-4-1.png") 275 358 276 359 # Output 2.4.2: gaussian random dithering … … 286 369 return dest 287 370 288 test242(lenna256bw).save("out2-4-2.png") 289 test242(gradient256bw).save("grad2-4-2.png") 371 if chapter(2): 372 test242(lenna256bw).save("out2-4-2.png") 373 test242(gradient256bw).save("grad2-4-2.png") 290 374 291 375 # Output 2.4.3: 4x4 Bayer dithering with gaussian perturbation … … 305 389 return dest 306 390 307 test243(lenna256bw, DITHER_BAYER88).save("out2-4-3.png") 308 test243(gradient256bw, DITHER_BAYER88).save("grad2-4-3.png") 391 if chapter(2): 392 test243(lenna256bw, DITHER_BAYER88).save("out2-4-3.png") 393 test243(gradient256bw, DITHER_BAYER88).save("grad2-4-3.png") 309 394 310 395 # Output 2.4.4: random dither matrice selection … … 326 411 return dest 327 412 328 m1 = [[1, 4, 7], 329 [6, 0, 2], 330 [3, 8, 5]] 331 m2 = [[4, 6, 3], 332 [8, 1, 5], 333 [0, 3, 7]] 334 m3 = [[5, 0, 3], 335 [2, 8, 6], 336 [7, 4, 1]] 337 m4 = [[8, 2, 5], 338 [6, 4, 0], 339 [1, 7, 3]] 340 m5 = [[2, 5, 8], 341 [0, 7, 3], 342 [4, 1, 6]] 343 m6 = [[7, 4, 1], 344 [3, 6, 8], 345 [2, 0, 5]] 346 mlist = [m1, m2, m3, m4, m5, m6] 347 test244(lenna256bw, mlist).save("out2-4-4.png") 348 test244(gradient256bw, mlist).save("grad2-4-4.png") 413 if chapter(2): 414 m1 = [[1, 4, 7], 415 [6, 0, 2], 416 [3, 8, 5]] 417 m2 = [[4, 6, 3], 418 [8, 1, 5], 419 [0, 3, 7]] 420 m3 = [[5, 0, 3], 421 [2, 8, 6], 422 [7, 4, 1]] 423 m4 = [[8, 2, 5], 424 [6, 4, 0], 425 [1, 7, 3]] 426 m5 = [[2, 5, 8], 427 [0, 7, 3], 428 [4, 1, 6]] 429 m6 = [[7, 4, 1], 430 [3, 6, 8], 431 [2, 0, 5]] 432 mlist = [m1, m2, m3, m4, m5, m6] 433 test244(lenna256bw, mlist).save("out2-4-4.png") 434 test244(gradient256bw, mlist).save("grad2-4-4.png") 349 435 350 436 ############################################################################## 351 print "Chapter 3. Error diffusion" 437 if chapter(3): 438 print "Chapter 3. Error diffusion" 352 439 353 440 # Output 3.0.1: naive error diffusion … … 363 450 # Output 3.2.7: Sierra's Filter Lite 364 451 # Output 3-2-8: Atkinson 452 def test3xx(src, mat, serpentine): 453 (w, h) = src.size() 454 dest = Image((w, h)) 455 lines = len(mat) 456 rows = len(mat[0]) 457 offset = mat[0].index(-1) 458 ey = [[0.] * (w + rows - 1) for x in range(lines)] 459 for y in range(h): 460 ex = [0.] * (rows - offset) 461 if serpentine and y & 1: 462 xrange = range(w - 1, -1, -1) 463 else: 464 xrange = range(w) 465 for x in xrange: 466 # Set pixel 467 c = src.getGray(x, y) + ex[0] + ey[0][x + offset] 468 d = c > 0.5 469 dest.setGray(x, y, d) 470 error = c - d 471 # Propagate first line of error 472 for dx in range(rows - offset - 2): 473 ex[dx] = ex[dx + 1] + error * mat[0][offset + 1 + dx] 474 ex[rows - offset - 2] = error * mat[0][rows - 1] 475 # Propagate next lines 476 if serpentine and y & 1: 477 for dy in range(1, lines): 478 for dx in range(rows): 479 ey[dy][x + dx] += error * mat[dy][rows - 1 - dx] 480 else: 481 for dy in range(1, lines): 482 for dx in range(rows): 483 ey[dy][x + dx] += error * mat[dy][dx] 484 for dy in range(lines - 1): 485 ey[dy] = ey[dy + 1] 486 ey[lines - 1] = [0.] * (w + rows - 1) 487 return dest 488 365 489 ERROR_NAIVE = \ 366 490 [[ -1, 1]] … … 409 533 # [ 2./200, 9./200, 12./200, 9./200, 2./200]] 410 534 411 def test3xx(src, mat, serpentine): 412 (w, h) = src.size() 413 dest = Image((w, h)) 414 lines = len(mat) 415 rows = len(mat[0]) 416 offset = mat[0].index(-1) 417 ey = [[0.] * (w + rows - 1) for x in range(lines)] 418 for y in range(h): 419 ex = [0.] * (rows - offset) 420 if serpentine and y & 1: 421 xrange = range(w - 1, -1, -1) 422 else: 423 xrange = range(w) 424 for x in xrange: 425 # Set pixel 426 c = src.getGray(x, y) + ex[0] + ey[0][x + offset] 427 d = c > 0.5 428 dest.setGray(x, y, d) 429 error = c - d 430 # Propagate first line of error 431 for dx in range(rows - offset - 2): 432 ex[dx] = ex[dx + 1] + error * mat[0][offset + 1 + dx] 433 ex[rows - offset - 2] = error * mat[0][rows - 1] 434 # Propagate next lines 435 if serpentine and y & 1: 436 for dy in range(1, lines): 437 for dx in range(rows): 438 ey[dy][x + dx] += error * mat[dy][rows - 1 - dx] 439 else: 440 for dy in range(1, lines): 441 for dx in range(rows): 442 ey[dy][x + dx] += error * mat[dy][dx] 443 for dy in range(lines - 1): 444 ey[dy] = ey[dy + 1] 445 ey[lines - 1] = [0.] * (w + rows - 1) 446 return dest 447 448 test3xx(lenna256bw, ERROR_NAIVE, False).save("out3-0-1.png") 449 test3xx(gradient256bw, ERROR_NAIVE, False).save("grad3-0-1.png") 450 451 test3xx(lenna256bw, ERROR_FSTEIN, False).save("out3-1-1.png") 452 test3xx(gradient256bw, ERROR_FSTEIN, False).save("grad3-1-1.png") 453 test3xx(lenna256bw, ERROR_FSTEIN, True).save("out3-1-2.png") 454 test3xx(gradient256bw, ERROR_FSTEIN, True).save("grad3-1-2.png") 455 456 test3xx(lenna256bw, ERROR_FAN, False).save("out3-2-1.png") 457 test3xx(gradient256bw, ERROR_FAN, False).save("grad3-2-1.png") 458 459 test3xx(lenna256bw, ERROR_JAJUNI, False).save("out3-2-2.png") 460 test3xx(gradient256bw, ERROR_JAJUNI, False).save("grad3-2-2.png") 461 462 test3xx(lenna256bw, ERROR_STUCKI, False).save("out3-2-3.png") 463 test3xx(gradient256bw, ERROR_STUCKI, False).save("grad3-2-3.png") 464 465 test3xx(lenna256bw, ERROR_BURKES, False).save("out3-2-4.png") 466 test3xx(gradient256bw, ERROR_BURKES, False).save("grad3-2-4.png") 467 468 test3xx(lenna256bw, ERROR_SIERRA, False).save("out3-2-5.png") 469 test3xx(gradient256bw, ERROR_SIERRA, False).save("grad3-2-5.png") 470 471 test3xx(lenna256bw, ERROR_SIERRA2, False).save("out3-2-6.png") 472 test3xx(gradient256bw, ERROR_SIERRA2, False).save("grad3-2-6.png") 473 474 test3xx(lenna256bw, ERROR_FILTERLITE, False).save("out3-2-7.png") 475 test3xx(gradient256bw, ERROR_FILTERLITE, False).save("grad3-2-7.png") 476 477 test3xx(lenna256bw, ERROR_ATKINSON, False).save("out3-2-8.png") 478 test3xx(gradient256bw, ERROR_ATKINSON, False).save("grad3-2-8.png") 479 480 #test3xx(lenna256bw, ERROR_STAR, False).save("out3-2-9.png") 481 #test3xx(gradient256bw, ERROR_STAR, False).save("grad3-2-9.png") 482 483 #test3xx(lenna256bw, ERROR_STAR, False).save("out3-2-9.png") 484 #test3xx(gradient256bw, ERROR_STAR, False).save("grad3-2-9.png") 535 if chapter(3): 536 test3xx(lenna256bw, ERROR_NAIVE, False).save("out3-0-1.png") 537 test3xx(gradient256bw, ERROR_NAIVE, False).save("grad3-0-1.png") 538 539 test3xx(lenna256bw, ERROR_FSTEIN, False).save("out3-1-1.png") 540 test3xx(gradient256bw, ERROR_FSTEIN, False).save("grad3-1-1.png") 541 test3xx(lenna256bw, ERROR_FSTEIN, True).save("out3-1-2.png") 542 test3xx(gradient256bw, ERROR_FSTEIN, True).save("grad3-1-2.png") 543 544 test3xx(lenna256bw, ERROR_FAN, False).save("out3-2-1.png") 545 test3xx(gradient256bw, ERROR_FAN, False).save("grad3-2-1.png") 546 547 test3xx(lenna256bw, ERROR_JAJUNI, False).save("out3-2-2.png") 548 test3xx(gradient256bw, ERROR_JAJUNI, False).save("grad3-2-2.png") 549 550 test3xx(lenna256bw, ERROR_STUCKI, False).save("out3-2-3.png") 551 test3xx(gradient256bw, ERROR_STUCKI, False).save("grad3-2-3.png") 552 553 test3xx(lenna256bw, ERROR_BURKES, False).save("out3-2-4.png") 554 test3xx(gradient256bw, ERROR_BURKES, False).save("grad3-2-4.png") 555 556 test3xx(lenna256bw, ERROR_SIERRA, False).save("out3-2-5.png") 557 test3xx(gradient256bw, ERROR_SIERRA, False).save("grad3-2-5.png") 558 559 test3xx(lenna256bw, ERROR_SIERRA2, False).save("out3-2-6.png") 560 test3xx(gradient256bw, ERROR_SIERRA2, False).save("grad3-2-6.png") 561 562 test3xx(lenna256bw, ERROR_FILTERLITE, False).save("out3-2-7.png") 563 test3xx(gradient256bw, ERROR_FILTERLITE, False).save("grad3-2-7.png") 564 565 test3xx(lenna256bw, ERROR_ATKINSON, False).save("out3-2-8.png") 566 test3xx(gradient256bw, ERROR_ATKINSON, False).save("grad3-2-8.png") 567 568 #test3xx(lenna256bw, ERROR_STAR, False).save("out3-2-9.png") 569 #test3xx(gradient256bw, ERROR_STAR, False).save("grad3-2-9.png") 570 571 #test3xx(lenna256bw, ERROR_STAR, False).save("out3-2-9.png") 572 #test3xx(gradient256bw, ERROR_STAR, False).save("grad3-2-9.png") 485 573 486 574 ############################################################################## 487 print "Chapter 4. Grayscale dithering" 575 if chapter(4): 576 print "Chapter 4. Grayscale dithering" 488 577 489 578 # Output 4.0.1: 4x4 Bayer dithering, 3 colours … … 504 593 return dest 505 594 506 test401(lenna256bw, DITHER_BAYER44).save("out4-0-1.png") 507 test401(gradient256bw, DITHER_BAYER44).save("grad4-0-1.png") 595 if chapter(4): 596 test401(lenna256bw, DITHER_BAYER44).save("out4-0-1.png") 597 test401(gradient256bw, DITHER_BAYER44).save("grad4-0-1.png") 508 598 509 599 # Output 4.0.2: standard Floyd-Steinberg, 3 colours … … 545 635 return dest 546 636 547 test402(lenna256bw, ERROR_FSTEIN, False).save("out4-0-2.png")548 test402(gradient256bw, ERROR_FSTEIN, False).save("grad4-0-2.png")637 test402(lenna256bw, ERROR_FSTEIN, False).save("out4-0-2.png") 638 test402(gradient256bw, ERROR_FSTEIN, False).save("grad4-0-2.png") 549 639 550 640 # Pattern 4.1.1: gamma-corrected 50% gray, black-white halftone, 50% gray 551 dest = Image((240, 80)) 552 for y in range(80): 553 for x in range(80): 554 dest.setGray(x, y, Gamma.ItoC(0.5)) 555 for x in range(80, 160): 556 c = (x + y) & 1 557 dest.setGray(x, y, c) 558 for x in range(160, 240): 559 dest.setGray(x, y, 0.5) 560 dest.save("pat4-1-1.png") 641 if chapter(4): 642 dest = Image((240, 80)) 643 for y in range(80): 644 for x in range(80): 645 dest.setGray(x, y, Gamma.ItoC(0.5)) 646 for x in range(80, 160): 647 c = (x + y) & 1 648 dest.setGray(x, y, c) 649 for x in range(160, 240): 650 dest.setGray(x, y, 0.5) 651 dest.save("pat4-1-1.png") 561 652 562 653 # Output 4.2.1: gamma-corrected 2-colour Floyd-Steinberg … … 591 682 return dest 592 683 593 def threshold_2(x): 594 if x < Gamma.CtoI(0.50): 595 return 0. 596 return 1. 597 598 def threshold_3(x): 599 if x < Gamma.CtoI(0.25): 600 return 0. 601 elif x < Gamma.CtoI(0.75): 602 return Gamma.CtoI(0.5) 603 return 1. 604 605 def threshold_4(x): 606 if x < Gamma.CtoI(0.17): 607 return 0. 608 elif x < Gamma.CtoI(0.50): 609 return Gamma.CtoI(0.3333) 610 elif x < Gamma.CtoI(0.83): 611 return Gamma.CtoI(0.6666) 612 return 1. 613 614 test42x(lenna256bw, ERROR_FSTEIN, threshold_2).save("out4-2-1.png") 615 test42x(gradient256bw, ERROR_FSTEIN, threshold_2).save("grad4-2-1.png") 616 test42x(lenna256bw, ERROR_FSTEIN, threshold_3).save("out4-2-2.png") 617 test42x(gradient256bw, ERROR_FSTEIN, threshold_3).save("grad4-2-2.png") 618 test42x(lenna256bw, ERROR_FSTEIN, threshold_4).save("out4-2-3.png") 619 test42x(gradient256bw, ERROR_FSTEIN, threshold_4).save("grad4-2-3.png") 684 if chapter(4): 685 test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto2).save("out4-2-1.png") 686 test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto2).save("grad4-2-1.png") 687 test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto3).save("out4-2-2.png") 688 test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto3).save("grad4-2-2.png") 689 test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto4).save("out4-2-3.png") 690 test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto4).save("grad4-2-3.png") 620 691 621 692 ############################################################################## 622 print "Chapter 5. Colour dithering" 693 if chapter(5): 694 print "Chapter 5. Colour dithering" 623 695 624 696 # Pattern 5.1.1: 8-colour palette 625 dest = Image((512, 64)) 626 for x in range(512): 627 d = x / 64 628 r = (d & 2) >> 1 629 g = (d & 4) >> 2 630 b = d & 1 631 for y in range(64): 632 dest.setRgb(x, y, r, g, b) 633 dest.save("pat5-1-1.png") 634 635 # Load the 256x256 colour Lenna image 636 lenna256 = Image("lenna256.png") 697 if chapter(5): 698 dest = Image((512, 64)) 699 for x in range(512): 700 d = x / 64 701 r = (d & 2) >> 1 702 g = (d & 4) >> 2 703 b = d & 1 704 for y in range(64): 705 dest.setRgb(x, y, r, g, b) 706 dest.save("pat5-1-1.png") 637 707 638 708 # Output 5.1.1: 8-colour Floyd-Steinberg RGB dithering … … 648 718 tmp[i].setGray(x, y, rgb[i]) 649 719 for i in range(3): 650 tmp[i] = func(tmp[i], mat, threshold_2)720 tmp[i] = func(tmp[i], mat, Gamma.Cto2) 651 721 for y in range(h): 652 722 for x in range(w): … … 655 725 return dest 656 726 657 test51x(lenna256, ERROR_FSTEIN, test3xx).save("out5-1-1.png") 658 out512 = test51x(lenna256, ERROR_FSTEIN, test42x) 659 out512.save("out5-1-2.png") 727 if chapter(5): 728 test51x(lenna256, ERROR_FSTEIN, test3xx).save("out5-1-1.png") 729 out512 = test51x(lenna256, ERROR_FSTEIN, test42x) 730 out512.save("out5-1-2.png") 660 731 661 732 # Pattern 5.2.1: different colours give the same result 662 dest = Image((320, 160)) 663 for x in range(80): 664 for y in range(80): 665 r = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 7 666 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 667 b = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 668 dest.setRgb(x, y, b, g, r) 669 for y in range(80, 160): 670 r = DITHER_BAYER44[y % 4][x % 4] > 7 671 g = DITHER_BAYER44[y % 4][x % 4] > 13 672 b = DITHER_BAYER44[y % 4][x % 4] > 13 673 dest.setRgb(x, y, b, g, r) 674 for x in range(80, 160): 675 for y in range(80): 676 r = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 7 677 g = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 1) % 4] > 13 678 b = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 1) % 4] > 13 679 dest.setRgb(x, y, b, g, r) 680 for y in range(80, 160): 681 r = DITHER_BAYER44[y % 4][x % 4] > 7 682 g = DITHER_BAYER44[y % 4][(x + 1) % 4] > 13 683 b = DITHER_BAYER44[y % 4][(x + 1) % 4] > 13 684 dest.setRgb(x, y, b, g, r) 685 for x in range(160, 240): 686 for y in range(80): 687 r = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8 + 1) % 4] > 7 688 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 689 b = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8) % 4] > 13 690 dest.setRgb(x, y, b, g, r) 691 for y in range(80, 160): 692 r = DITHER_BAYER44[(y + 1) % 4][(x + 1) % 4] > 7 693 g = DITHER_BAYER44[y % 4][x % 4] > 13 694 b = DITHER_BAYER44[(y + 1) % 4][x % 4] > 13 695 dest.setRgb(x, y, b, g, r) 696 for x in range(240, 320): 697 for y in range(80): 698 r = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8) % 4] > 7 699 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 700 b = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 2) % 4] > 13 701 dest.setRgb(x, y, b, g, r) 702 for y in range(80, 160): 703 r = DITHER_BAYER44[(y + 1) % 4][x % 4] > 7 704 g = DITHER_BAYER44[y % 4][x % 4] > 13 705 b = DITHER_BAYER44[y % 4][(x + 2) % 4] > 13 706 dest.setRgb(x, y, b, g, r) 707 dest.save("pat5-2-1.png") 733 def chapter5(): 734 dest = Image((320, 160)) 735 for x in range(80): 736 for y in range(80): 737 r = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 7 738 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 739 b = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 740 dest.setRgb(x, y, b, g, r) 741 for y in range(80, 160): 742 r = DITHER_BAYER44[y % 4][x % 4] > 7 743 g = DITHER_BAYER44[y % 4][x % 4] > 13 744 b = DITHER_BAYER44[y % 4][x % 4] > 13 745 dest.setRgb(x, y, b, g, r) 746 for x in range(80, 160): 747 for y in range(80): 748 r = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 7 749 g = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 1) % 4] > 13 750 b = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 1) % 4] > 13 751 dest.setRgb(x, y, b, g, r) 752 for y in range(80, 160): 753 r = DITHER_BAYER44[y % 4][x % 4] > 7 754 g = DITHER_BAYER44[y % 4][(x + 1) % 4] > 13 755 b = DITHER_BAYER44[y % 4][(x + 1) % 4] > 13 756 dest.setRgb(x, y, b, g, r) 757 for x in range(160, 240): 758 for y in range(80): 759 r = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8 + 1) % 4] > 7 760 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 761 b = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8) % 4] > 13 762 dest.setRgb(x, y, b, g, r) 763 for y in range(80, 160): 764 r = DITHER_BAYER44[(y + 1) % 4][(x + 1) % 4] > 7 765 g = DITHER_BAYER44[y % 4][x % 4] > 13 766 b = DITHER_BAYER44[(y + 1) % 4][x % 4] > 13 767 dest.setRgb(x, y, b, g, r) 768 for x in range(240, 320): 769 for y in range(80): 770 r = DITHER_BAYER44[(y / 8 + 1) % 4][(x / 8) % 4] > 7 771 g = DITHER_BAYER44[(y / 8) % 4][(x / 8) % 4] > 13 772 b = DITHER_BAYER44[(y / 8) % 4][(x / 8 + 2) % 4] > 13 773 dest.setRgb(x, y, b, g, r) 774 for y in range(80, 160): 775 r = DITHER_BAYER44[(y + 1) % 4][x % 4] > 7 776 g = DITHER_BAYER44[y % 4][x % 4] > 13 777 b = DITHER_BAYER44[y % 4][(x + 2) % 4] > 13 778 dest.setRgb(x, y, b, g, r) 779 dest.save("pat5-2-1.png") 708 780 709 781 # Output 5.2.1: cropped 5.1.2 … … 719 791 return dest 720 792 721 test52x(out512, 20, 70, 32, 32, 1).save("out5-2-1.png") 722 test52x(out512, 20, 70, 32, 32, 6).save("out5-2-2.png") 723 724 out523 = test51x(lenna256, ERROR_STUCKI, test42x) 725 out523.save("out5-2-3.png") 726 test52x(out523, 20, 70, 32, 32, 1).save("out5-2-4.png") 727 test52x(out523, 20, 70, 32, 32, 6).save("out5-2-5.png") 793 if chapter(5): 794 test52x(out512, 20, 70, 32, 32, 1).save("out5-2-1.png") 795 test52x(out512, 20, 70, 32, 32, 6).save("out5-2-2.png") 796 797 out523 = test51x(lenna256, ERROR_STUCKI, test42x) 798 out523.save("out5-2-3.png") 799 test52x(out523, 20, 70, 32, 32, 1).save("out5-2-4.png") 800 test52x(out523, 20, 70, 32, 32, 6).save("out5-2-5.png") 801 802 ############################################################################## 803 if chapter(6): 804 print "Chapter 6. Photographic mosaics" 728 805 729 806 ############################################################################## … … 731 808 732 809 # Place temporary cruft below this 733 import sys;sys.exit(0)734 810 sys.exit(0) 811
Note: See TracChangeset
for help on using the changeset viewer.