Changeset 2030


Ignore:
Timestamp:
Nov 19, 2007, 1:40:48 AM (13 years ago)
Author:
Sam Hocevar
Message:
  • Started part 6: Photographic mosaics.
Location:
www/study
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • www/study/index.html

    r2029 r2030  
    8080  <li> <a href="part4.html">4. Grayscale dithering</a> </li>
    8181  <li> <a href="part5.html">5. Colour dithering</a> </li>
     82  <li> <a href="part6.html">6. Photographic mosaics</a> </li>
    8283</ul>
    8384
  • www/study/part5.html

    r2027 r2030  
    2828   <a href="part4.html">Grayscale dithering &lt;&lt;&lt;</a>
    2929</div>
    30 <!--<div style="float: right;">
    31    <a href=""></a>
    32 </div>-->
     30<div style="float: right;">
     31   <a href="part6.html">&gt;&gt;&gt; Photographic mosaics</a>
     32</div>
    3333<div style="text-align: center;">
    3434   <a href="index.html">^^^ Index</a>
     
    117117   <a href="part4.html">Grayscale dithering &lt;&lt;&lt;</a>
    118118</div>
    119 <!--<div style="float: right;">
    120    <a href=""></a>
    121 </div>-->
     119<div style="float: right;">
     120   <a href="part6.html">&gt;&gt;&gt; Photographic mosaics</a>
     121</div>
    122122<div style="text-align: center;">
    123123   <a href="index.html">^^^ Index</a>
  • www/study/study.py

    r2029 r2030  
    1313# Tiny image class to make examples short and readable
    1414class Image(gd.image):
     15    gd.gdMaxColors = 256 * 256 * 256
    1516    def __init__(self, *args):
    16         gd.gdMaxColors = 256 * 256 * 256
    1717        if args[0].__class__ == str:
    1818            print " * loading %s" % (args[0],)
     
    804804    print "Chapter 6. Photographic mosaics"
    805805
     806# Output 6.0.1: create a mosaic from Lenna
     807def mosaic_split(src, tnw, tnh):
     808    random.seed(0)
     809    thumbs = []
     810    (w, h) = src.size()
     811    sw = w / tnw
     812    sh = h / tnh
     813    for y in range(sh):
     814        for x in range(sw):
     815            tmp = Image((tnw, tnh), True)
     816            for j in range(tnh):
     817                for i in range(tnw):
     818                    rgb = src.getRgb(x * tnw + i, y * tnh + j)
     819                    tmp.setRgb(i, j, *rgb)
     820            thumbs.append(tmp)
     821    random.shuffle(thumbs)
     822    return thumbs
     823
     824def mosaic_analyse(tnlist, dx, dy):
     825    coeffs = []
     826    for (n, img) in enumerate(tnlist):
     827        tmp = [[[0] * 3 for x in range(dx)] for y in range(dy)]
     828        (w, h) = img.size()
     829        for y in range(h):
     830            my = y * dy / h
     831            for x in range(w):
     832                mx = x * dx / w
     833                (r, g, b) = img.getRgb(x, y)
     834                tmp[my][mx][0] += Gamma.CtoI(r) / (w / dx * h / dy)
     835                tmp[my][mx][1] += Gamma.CtoI(g) / (w / dx * h / dy)
     836                tmp[my][mx][2] += Gamma.CtoI(b) / (w / dx * h / dy)
     837        coeffs.append(tmp)
     838    return coeffs
     839
     840def test603(src, sqw, sqh, tnlist, coeffs, dx, dy):
     841    (w, h) = src.size()
     842    (tnw, tnh) = tnlist[0].size()
     843    nx = w / sqw
     844    ny = h / sqh
     845    dest = Image((nx * tnw, ny * tnh), True)
     846    for Y in range(ny):
     847        for X in range(nx):
     848            # 1. create statistics about the current square
     849            cur = [[[0] * 3 for x in range(dx)] for y in range(dy)]
     850            for y in range(sqh):
     851                my = y * dy / sqh
     852                for x in range(sqw):
     853                    mx = x * dx / sqw
     854                    (r, g, b) = src.getRgb(X * sqw + x, Y * sqh + y)
     855                    cur[my][mx][0] += Gamma.CtoI(r) / (sqw / dx * sqh / dy)
     856                    cur[my][mx][1] += Gamma.CtoI(g) / (sqw / dx * sqh / dy)
     857                    cur[my][mx][2] += Gamma.CtoI(b) / (sqw / dx * sqh / dy)
     858            # 2. find the best mosaic part
     859            best = -1
     860            dist = 5.
     861            for (n, tmp) in enumerate(coeffs):
     862                d = 0
     863                for j in range(dy):
     864                    for i in range(dx):
     865                        for c in range(3):
     866                            t = cur[j][i][c] - tmp[j][i][c]
     867                            d += t * t
     868                if d < dist:
     869                    dist = d
     870                    best = n
     871            # 3. blit mosaic chunk
     872            tnlist[best].copyTo(dest, (X * tnw, Y * tnh))
     873    return dest
     874
     875def test602(src, x, y, w, h):
     876    dest = Image((w, h), True)
     877    src.copyTo(dest, (-x, -y))
     878    return dest
     879
     880def test601(tnlist, cols):
     881    (tnw, tnh) = tnlist[0].size()
     882    dw = cols
     883    dh = (len(tnlist) + cols - 1) / cols
     884    dest = Image((dw * tnw + 8 * (dw + 1), dh * tnh + 8 * (dh + 1)), True)
     885    for (n, img) in enumerate(tnlist):
     886        di = 8 + (n % dw) * (tnw + 8)
     887        dj = 8 + (n / dw) * (tnh + 8)
     888        for y in range(tnh):
     889            for x in range(tnw):
     890                (r, g, b) = img.getRgb(x, y)
     891                dest.setRgb(di + x, dj + y, r, g, b)
     892    return dest
     893
     894if chapter(6):
     895    tnlist = mosaic_split(lenna256, 32, 32)
     896    coeffs = mosaic_analyse(tnlist, 2, 2)
     897    test601(tnlist, 10).save("out6-0-1.png")
     898    out602 = test602(lenna256, 100, 90, 80, 80)
     899    out602.save("out6-0-2.png")
     900    test603(out602, 6, 6, tnlist, coeffs, 2, 2).save("out6-0-3.png")
     901
    806902##############################################################################
    807903print "Finished"
Note: See TracChangeset for help on using the changeset viewer.