# Changeset 1931 for wwwTweet

Ignore:
Timestamp:
Nov 11, 2007, 1:27:43 PM (13 years ago)
Message:
• Started error diffusion part. Added Floyd-Steinberg.
Location:
www/study
Files:
2 edited

Unmodified
Removed
• ## www/study/index.html

 r1930

2.3. Ordered dither

2.3. Ordered dithering

A generalisation of the dithering technique we just saw that uses a certain family of patterns is called ordered dither. It is based on certain family of patterns is called ordered dithering. It is based on a dither matrix such as the following one:

Different matrices can give very different results. This is a 4×4 Bayer ordered dither matrix:

Bayer ordered dithering matrix:

class="inline" alt="4x4 cluster dot dithering gradient" />

There are two major issues with ordered dithering. First, important visual artifacts may appear. Even the Bayer ordered dithering causes weird cross-hatch pattern artifacts on some images. Second, dithering matrices do not depend on the original image and thus do not take input data into account: high frequency features in the image is often missed and, in some cases, cause even worse artifacts.

3. Error diffusion

The idea behind error diffusion is to compute the error caused by thresholding a given pixel and propagate it to neighbour pixels.

3.1. Floyd-Steinberg error diffusion

The most famous error diffusion method is the Floyd-Steinberg algorithm. It handles each pixel of the image one after the other and propagates the error to adjacent pixels:

The error is computed by simply substracting the source value and the destination value. Destination value can be chosen by many means but does not impact the image a lot compared to the error distribution coefficients choice. Here is the result using a 0.5 threshold:

• ## www/study/study.py

 r1930 # Output 7: 4x4 Bayer dithering # Output 8: 4x4 cluster dot # Output 9: 5x3 line dithering def test4(src, mat, name): (w, h) = src.size() test4(lenna256bw, mat, "out009.png") test4(gradient256bw, mat, "grad009.png") # Output 10: standard Floyd-Steinberg def test5(src, name): (w, h) = src.size() dest = Image((w, h)) ep = [0.] * (w + 2) for y in range(h): en = [0.] * (w + 2) #print 'ep:', ep #print 'en:', en ex = 0 for x in range(w): c = src.getGray(x, y) + ex + ep[x + 1] d = c > 0.5 dest.setGray(x, y, d) error = c - d ex = error * 7. / 16. en[x] += error * 3. / 16. en[x + 1] += error * 5. / 16. en[x + 2] += error * 1. / 16. ep = en dest.writePng(name) test5(lenna256bw, "out010.png") test5(gradient256bw, "grad010.png") ##############################################################################
Note: See TracChangeset for help on using the changeset viewer.