PaletteOptimiser

Changeset

35:baa08ae98f2e
2015-10-03 Paul Boddie raw files shortlog changelog graph Added a "balancing" function to remove primary/secondary complement pairs, thus removing colour noise and simplifying the job of the optimisation routine. Added the useful preview function back to the program. Removed some working notes.
optimiser.py (file)
     1.1 --- a/optimiser.py	Sat Oct 03 16:52:17 2015 +0200
     1.2 +++ b/optimiser.py	Sat Oct 03 19:08:11 2015 +0200
     1.3 @@ -23,6 +23,9 @@
     1.4      l.sort()
     1.5      return l[0][1]
     1.6  
     1.7 +def restore(srgb):
     1.8 +    return tuple(map(lambda x: int(x * 255.0), srgb))
     1.9 +
    1.10  def scale(rgb):
    1.11      return tuple(map(lambda x: x / 255.0, rgb))
    1.12  
    1.13 @@ -37,7 +40,21 @@
    1.14      for corner in corners:
    1.15          rs, gs, bs = scale(corner)
    1.16          d.append((pairs[0][int(rs)] * pairs[1][int(gs)] * pairs[2][int(bs)], corner))
    1.17 -    return d
    1.18 +    return balance(d)
    1.19 +
    1.20 +def complements(rgb):
    1.21 +    r, g, b = rgb
    1.22 +    return rgb, restore(invert(scale(rgb)))
    1.23 +
    1.24 +def balance(d):
    1.25 +    d = dict([(value, f) for f, value in d])
    1.26 +    for primary, secondary in map(complements, [(255, 0, 0), (0, 255, 0), (0, 0, 255)]):
    1.27 +        common = min(d[primary], d[secondary])
    1.28 +        d[primary] -= common
    1.29 +        d[secondary] -= common
    1.30 +        d[(0, 0, 0)] += common
    1.31 +        d[(255, 255, 255)] += common
    1.32 +    return [(f, value) for value, f in d.items()]
    1.33  
    1.34  def combine(d):
    1.35      out = [0, 0, 0]
    1.36 @@ -47,30 +64,6 @@
    1.37          out[2] += v * rgb[2]
    1.38      return out
    1.39  
    1.40 -"""
    1.41 -r(R - K)
    1.42 -r(Y - G)
    1.43 -r(M - B)
    1.44 -r(W - C)
    1.45 -g(G - K)
    1.46 -g(Y - R)
    1.47 -g(C - B)
    1.48 -g(W - M)
    1.49 -b(B - K)
    1.50 -b(M - R)
    1.51 -b(C - G)
    1.52 -b(W - Y)
    1.53 -
    1.54 -b(g(r(W - C) - r(M - B)) - g(r(Y - G) - r(R - K)))
    1.55 -b(r(g(W - M) - g(C - B)) - r(g(Y - R) - g(G - K)))
    1.56 -
    1.57 -b(g(rW + riC) + gi(rM + riB)) + bi(g(rY + riG) + gi(rR + riK))
    1.58 -b(r(gW + giM) + ri(gC + giB)) + bi(r(gY + giR) + ri(gG + giK))
    1.59 -
    1.60 -W(b.g.r) + C(b.g.ri) + M(b.gi.r) + B(b.g.ri) + Y(bi.g.r) + G(bi.g.ri) + R(bi.gi.r) + K(bi.gi.ri)
    1.61 -...
    1.62 -"""
    1.63 -
    1.64  def pattern(rgb):
    1.65      l = combination(rgb)
    1.66      l.sort(reverse=True)
    1.67 @@ -144,10 +137,12 @@
    1.68  
    1.69      input_filename, output_filename = sys.argv[1:3]
    1.70      basename, ext = splitext(output_filename)
    1.71 +    preview_filename = "".join([basename + "_preview", ext])
    1.72  
    1.73      rotate = "-r" in sys.argv[3:]
    1.74      saturate = sys.argv[3:].count("-s")
    1.75      desaturate = sys.argv[3:].count("-d")
    1.76 +    preview = "-p" in sys.argv[3:]
    1.77  
    1.78      x = EXIF.process_file(open(input_filename))
    1.79      im = PIL.Image.open(input_filename).convert("RGB")
    1.80 @@ -180,6 +175,15 @@
    1.81          c.sort(reverse=True)
    1.82          colours.append(c)
    1.83  
    1.84 +    if preview:
    1.85 +        imp = im.copy()
    1.86 +        for y in range(0, height):
    1.87 +            for x in range(0, width):
    1.88 +                rgb = imp.getpixel((x, y))
    1.89 +                value = get_value(rgb)
    1.90 +                imp.putpixel((x, y), value)
    1.91 +        imp.save(preview_filename)
    1.92 +
    1.93      for y, c in enumerate(colours):
    1.94          most = [value for n, value in c[:4]]
    1.95          least = [value for n, value in c[4:]]