Changeset 1930
- Timestamp:
- 11/11/07 13:27:40 (6 years ago)
- Location:
- www/study
- Files:
-
- 13 added
- 5 edited
-
fig001.png (added)
-
fig001.svg (added)
-
fig002.png (added)
-
fig002.svg (added)
-
fig003.png (added)
-
fig003.svg (added)
-
fig004.png (added)
-
fig004.svg (added)
-
grad007.png (modified) (previous)
-
grad008.png (added)
-
grad009.png (added)
-
gradient256bw.png (added)
-
index.html (modified) (5 diffs)
-
out007.png (modified) (previous)
-
out008.png (added)
-
out009.png (added)
-
pat004.png (modified) (previous)
-
study.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
www/study/index.html
r1926 r1930 40 40 <img src="lenna256bw.png" width="256" height="256" 41 41 class="inline" alt="Lenna (256x256BW)" /> 42 <img src="gradient256bw.png" width="32" height="256" 43 class="inline" alt="gradient" /> 42 44 </p> 43 45 … … 106 108 </p> 107 109 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 112 not improve tremendously. </p> 109 113 110 114 <h3> 1.2. Grayscale thresholding </h3> … … 172 176 </p> 173 177 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 179 computer screen. Optimising patterns so that they look good to the human 180 eye and don't create artifacts is a crucial element of a dithering 181 algorithm. Here is another example of two patterns that approximate to 182 the 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 192 certain family of patterns is called <b>ordered dither</b>. It is based on 193 a <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 200 as threshold values. In this case, pixels (0,0), (0,2), (0,4) etc. will be 201 thresholded with a value of 0.2. Pixels (0,1), (0, 3), (0, 4) etc. will be 202 thresholded with a value of 0.8, and so on, resulting in the image seen 203 in 2.1. </p> 204 205 <p> Different matrices can give very different results. This is a 4×4 206 Bayer 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 218 halftoning 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 179 244 screen, you may have noticed that the above 50% pattern was closer to a 0.73 180 245 grayscale (left) than to the intuitively expected 0.5 value (right). If you … … 195 260 196 261 <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" /> 198 263 </p> 199 264 … … 227 292 <img src="grad007.png" width="32" height="256" 228 293 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 --> 232 296 233 297 <!-- 298 <h3> Gamma with more gray levels </h3> 299 300 <p> As seen above, the smoothest dithering pattern that can be created with 301 black and white is by uniformly alterning the two colours. However, the 302 resulting colour (0.73) it is not evenly situated on the gray scale. </p> 303 234 304 <img src="out008.png" width="256" height="256" 235 305 class="inline" alt="gamma-aware 6.25%, 25% and 50% halftoning" /> -
www/study/study.py
r1927 r1930 47 47 for y in range(256): 48 48 gradient256bw.setGray(x, 255 - y, y / 255.) 49 gradient256bw.writePng("gradient256bw.png") 49 50 50 51 # Output 1: 50% threshold … … 143 144 dest.setGray(x, y, c) 144 145 dest.writePng("pat003.png") 146 147 # Pattern 4: two different 25% patterns 148 dest = Image((320, 80)) 149 for 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) 162 dest.writePng("pat004.png") 163 164 # Output 7: 4x4 Bayer dithering 165 def 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 178 mat = [[ 0, 8, 3, 11], 179 [ 15, 4, 12, 7], 180 [ 2, 10, 1, 9], 181 [ 13, 6, 14, 5]] 182 test4(lenna256bw, mat, "out007.png") 183 test4(gradient256bw, mat, "grad007.png") 184 185 mat = [[ 12, 5, 6, 13], 186 [ 4, 0, 1, 7], 187 [ 11, 3, 2, 8], 188 [ 15, 10, 9, 14]] 189 test4(lenna256bw, mat, "out008.png") 190 test4(gradient256bw, mat, "grad008.png") 191 192 mat = [[ 13, 7, 0, 4, 10], 193 [ 9, 3, 1, 8, 14], 194 [ 11, 5, 2, 6, 12],] 195 test4(lenna256bw, mat, "out009.png") 196 test4(gradient256bw, mat, "grad009.png") 197 198 ############################################################################## 199 # Only temporary cruft below this 200 import sys 201 sys.exit(0) 202 203 204 145 205 146 206 # Pattern 4: gamma-corrected 50% gray, black-white halftone, 50% gray … … 213 273 214 274 215 ##############################################################################216 # Only temporary cruft below this217 218 275 src = lenna256bw 219 276 src = gradient256bw … … 224 281 [ 2, 10, 1, 9], 225 282 [ 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]] 291 size = 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 246 305 dest = Image((w, h)) 247 306 for y in range(h): … … 249 308 c = src.getGray(x, y) 250 309 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 253 315 dest.setGray(x, y, c) 254 316 dest.writePng("out008.png") 255 256 import sys257 sys.exit(0)258 317 259 318 # Create a dot-matrix pattern
Note: See TracChangeset
for help on using the changeset viewer.
