Changeset 2130


Ignore:
Timestamp:
Dec 7, 2007, 10:39:04 AM (13 years ago)
Author:
Sam Hocevar
Message:
  • Use serpentine FS instead of classical FS.
  • Remove the crap about FS artifacts in colour dithering.
Location:
www/study
Files:
5 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • www/study/part3.html

    r2127 r2130  
    272272<p> Ostromoukhov’s variable coefficients error diffusion uses a small
    273273matrix, which usually causes a lot of artifacts to appear. However, the
    274 coefficients here vary according to the input value, and the list of 256
    275 discrete value triplets for <i>d1</i>, <i>d2</i> and <i>d3</i> provided by
    276 Ostromoukhov give pretty good results: </p>
     274error diffusion values here are not constant. They vary according to the input
     275value, and the list of 256 discrete value triplets for <i>d1</i>, <i>d2</i>
     276and <i>d3</i> provided by Ostromoukhov give pretty good results with
     277serpentine parsing: </p>
    277278
    278279<p style="text-align: center;">
  • www/study/part4.html

    r2034 r2130  
    4141pixels in the [0, 0.5] range with black and gray, and pixels in the [0.5, 1]
    4242range with gray and white. Here are two different results with 4×4 Bayer
    43 ordered dithering and with Floyd-Steinberg error diffusion: </p>
     43ordered dithering and with serpentine Floyd-Steinberg error diffusion: </p>
    4444
    4545<p style="text-align: center;">
     
    4949       class="inline" alt="4×4 Bayer ordered dithering gradient, 3 colours" />
    5050  <img src="out4-0-2.png" width="256" height="256"
    51        class="inline" alt="Floyd-Steinberg error diffusion, 3 colours" />
     51       class="inline" alt="serpentine FS error diffusion, 3 colours" />
    5252  <img src="grad4-0-2.png" width="32" height="256"
    53        class="inline" alt="Floyd-Steinberg error diffusion gradient, 3 colours" />
     53       class="inline" alt="serpentine FS error diffusion gradient, 3 colours" />
    5454</p>
    5555
     
    138138
    139139<p> Here are the results of gamma-correcting input pixels before doing
    140 any computation on them, then using Floyd-Steinberg error diffusion: </p>
     140any computation on them, then using serpentine Floyd-Steinberg error
     141diffusion: </p>
    141142
    142143<p style="text-align: center;">
    143144  <img src="out4-2-1.png" width="256" height="256"
    144        class="inline" alt="Floyd-Steinberg, 2 colours, gamma-corrected" />
     145       class="inline" alt="serpentine FS, 2 colours, gamma-corrected" />
    145146  <img src="grad4-2-1.png" width="32" height="256"
    146        class="inline" alt="Floyd-Steinberg, 2 colours, gamma-corrected gradient" />
     147       class="inline" alt="serpentine FS, 2 colours, gamma-corrected gradient" />
    147148  <img src="out4-2-2.png" width="256" height="256"
    148        class="inline" alt="Floyd-Steinberg, 3 colours, gamma-corrected" />
     149       class="inline" alt="serpentine FS, 3 colours, gamma-corrected" />
    149150  <img src="grad4-2-2.png" width="32" height="256"
    150        class="inline" alt="Floyd-Steinberg, 3 colours, gamma-corrected gradient" />
     151       class="inline" alt="serpentine FS, 3 colours, gamma-corrected gradient" />
    151152</p>
    152153
     
    162163<p style="text-align: center;">
    163164  <img src="out4-2-3.png" width="256" height="256"
    164        class="inline" alt="Floyd-Steinberg, 4 colours, gamma-corrected" />
     165       class="inline" alt="serpentine FS, 4 colours, gamma-corrected" />
    165166  <img src="grad4-2-3.png" width="32" height="256"
    166        class="inline" alt="Floyd-Steinberg, 4 colours, gamma-corrected gradient" />
     167       class="inline" alt="serpentine FS, 4 colours, gamma-corrected gradient" />
    167168</p>
    168169
  • www/study/part5.html

    r2030 r2130  
    5959the images into three channels. </p>
    6060
    61 <p> Here are the results with Floyd-Steinberg dithering applied to each
    62 channel. On the left, no colour correction, as The Gimp or Photoshop would
     61<p> Here are the results with serpentine Floyd-Steinberg dithering applied to
     62each channel. On the left, no colour correction, as The Gimp or Photoshop would
    6363do; on the right, gamma-corrected dithering: </p>
    6464
    6565<p style="text-align: center;">
    6666  <img src="out5-1-1.png" width="256" height="256"
    67        class="inline" alt="Floyd-Steinberg, 8 colours" />
     67       class="inline" alt="serpentine FS, 8 colours" />
    6868  <img src="out5-1-2.png" width="256" height="256"
    69        class="inline" alt="Floyd-Steinberg, 8 colours, gamma-corrected" />
     69       class="inline" alt="serpentine FS, 8 colours, gamma-corrected" />
    7070</p>
    7171
     
    8282  <img src="pat5-2-1.png" width="320" height="160"
    8383       class="inline" alt="3 ways to dither the same colour" />
    84 </p>
    85 
    86 <p> It is therefore quite clear that the exact pixel values matter much less
    87 than visual artifacts. Here is a close-up of the previous output’s top-left
    88 corner. The slanted bright pixel lines that appear are typical Floyd-Steinberg
    89 artifacts. They are rendered even worse by the fact that dithering is done on
    90 three different dimensions that do not take the others into account: </p>
    91 
    92 <p style="text-align: center;">
    93   <img src="out5-2-1.png" width="32" height="32"
    94        class="inlinetop" alt="Floyd-Steinberg, 8 colours, gamma-corrected, cropped" />
    95   <img src="out5-2-2.png" width="192" height="192"
    96        class="inline" alt="Floyd-Steinberg, 8 colours, gamma-corrected, cropped, zoomed" />
    97 </p>
    98 
    99 <p> Some algorithms perform a bit better in this area. This is Stucki
    100 dithering. The Floyd-Steinberg artifacts are much less visible: </p>
    101 
    102 <p style="text-align: center;">
    103   <img src="out5-2-3.png" width="256" height="256"
    104        class="inline" alt="Stucki, 8 colours, gamma-corrected" />
    105 </p>
    106 
    107 <p> And this is a close-up of the same area: </p>
    108 
    109 <p style="text-align: center;">
    110   <img src="out5-2-4.png" width="32" height="32"
    111        class="inlinetop" alt="Stucki, 8 colours, gamma-corrected, cropped" />
    112   <img src="out5-2-5.png" width="192" height="192"
    113        class="inline" alt="Stucki, 8 colours, gamma-corrected, cropped, zoomed" />
    11484</p>
    11585
  • www/study/study.py

    r2127 r2130  
    935935
    936936if chapter(4):
    937     test402(lenna256bw, ERROR_FSTEIN, False).save("out4-0-2.png")
    938     test402(gradient256bw, ERROR_FSTEIN, False).save("grad4-0-2.png")
     937    test402(lenna256bw, ERROR_FSTEIN, True).save("out4-0-2.png")
     938    test402(gradient256bw, ERROR_FSTEIN, True).save("grad4-0-2.png")
    939939
    940940# Pattern 4.1.1: gamma-corrected 50% gray, black-white halftone, 50% gray
     
    954954# Output 4.2.2: gamma-corrected 3-colour Floyd-Steinberg
    955955# Output 4.2.3: gamma-corrected 4-colour Floyd-Steinberg
    956 def test42x(src, mat, threshold):
     956def test42x(src, mat, serpentine, threshold):
    957957    (w, h) = src.size()
    958958    dest = Image((w, h))
     
    963963    for y in range(h):
    964964        ex = [0.] * (rows - offset)
    965         for x in range(w):
     965        if serpentine and y & 1:
     966            xrange = range(w - 1, -1, -1)
     967        else:
     968            xrange = range(w)
     969        for x in xrange:
    966970            # Set pixel
    967971            c = Gamma.CtoI(src.getGray(x, y)) + ex[0] + ey[0][x + offset]
     
    974978            ex[rows - offset - 2] = error * mat[0][rows - 1]
    975979            # Propagate next lines
    976             for dy in range(1, lines):
    977                 for dx in range(rows):
    978                     ey[dy][x + dx] += error * mat[dy][dx]
     980            if serpentine and y & 1:
     981                for dy in range(1, lines):
     982                    for dx in range(rows):
     983                        ey[dy][x + dx] += error * mat[dy][rows - 1 - dx]
     984            else:
     985                for dy in range(1, lines):
     986                    for dx in range(rows):
     987                        ey[dy][x + dx] += error * mat[dy][dx]
    979988        for dy in range(lines - 1):
    980989            ey[dy] = ey[dy + 1]
     
    983992
    984993if chapter(4):
    985     test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto2).save("out4-2-1.png")
    986     test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto2).save("grad4-2-1.png")
    987     test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto3).save("out4-2-2.png")
    988     test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto3).save("grad4-2-2.png")
    989     test42x(lenna256bw, ERROR_FSTEIN, Gamma.Cto4).save("out4-2-3.png")
    990     test42x(gradient256bw, ERROR_FSTEIN, Gamma.Cto4).save("grad4-2-3.png")
     994    test42x(lenna256bw, ERROR_FSTEIN, True, Gamma.Cto2).save("out4-2-1.png")
     995    test42x(gradient256bw, ERROR_FSTEIN, True, Gamma.Cto2).save("grad4-2-1.png")
     996    test42x(lenna256bw, ERROR_FSTEIN, True, Gamma.Cto3).save("out4-2-2.png")
     997    test42x(gradient256bw, ERROR_FSTEIN, True, Gamma.Cto3).save("grad4-2-2.png")
     998    test42x(lenna256bw, ERROR_FSTEIN, True, Gamma.Cto4).save("out4-2-3.png")
     999    test42x(gradient256bw, ERROR_FSTEIN, True, Gamma.Cto4).save("grad4-2-3.png")
    9911000
    9921001##############################################################################
     
    10181027                tmp[i].setGray(x, y, rgb[i])
    10191028    for i in range(3):
    1020         tmp[i] = func(tmp[i], mat, Gamma.Cto2)
     1029        tmp[i] = func(tmp[i], mat, True, Gamma.Cto2)
    10211030    for y in range(h):
    10221031        for x in range(w):
     
    10251034    return dest
    10261035
     1036def test51y(src, mat, serpentine, threshold):
     1037    return test3xx(src, mat, serpentine)
     1038
    10271039if chapter(5):
    1028     test51x(lenna256, ERROR_FSTEIN, test3xx).save("out5-1-1.png")
     1040    test51x(lenna256, ERROR_FSTEIN, test51y).save("out5-1-1.png")
    10291041    out512 = test51x(lenna256, ERROR_FSTEIN, test42x)
    10301042    out512.save("out5-1-2.png")
     
    10791091    dest.save("pat5-2-1.png")
    10801092
    1081 # Output 5.2.1: cropped 5.1.2
    1082 # Output 5.2.2: close-up of cropped 5.1.2
    1083 if chapter(5):
    1084     tmp = out512.getRegion(20, 70, 32, 32)
    1085     tmp.save("out5-2-1.png")
    1086     tmp.getZoom(6).save("out5-2-2.png")
    1087 
    1088     out523 = test51x(lenna256, ERROR_STUCKI, test42x)
    1089     out523.save("out5-2-3.png")
    1090     tmp = out523.getRegion(20, 70, 32, 32)
    1091     tmp.save("out5-2-4.png")
    1092     tmp.getZoom(6).save("out5-2-5.png")
    1093 
    10941093##############################################################################
    10951094if chapter(6):
Note: See TracChangeset for help on using the changeset viewer.