PaletteOptimiser

Changeset

34:9060af8f5ef5
2015-10-03 Paul Boddie raw files shortlog changelog graph Adopt a more thorough model of colour selection.
optimiser.py (file)
     1.1 --- a/optimiser.py	Sat Oct 03 01:32:26 2015 +0200
     1.2 +++ b/optimiser.py	Sat Oct 03 16:52:17 2015 +0200
     1.3 @@ -18,26 +18,68 @@
     1.4      r2, g2, b2 = rgb2
     1.5      return math.sqrt(pow(r1 - r2, 2) + pow(g1 - g2, 2) + pow(b1 - b2, 2))
     1.6  
     1.7 -def distribution(rgb, values=None):
     1.8 -    l = []
     1.9 -    total = 0
    1.10 -    for c in values or corners:
    1.11 -        d = distance(rgb, c)
    1.12 -        if d == 0:
    1.13 -            return [(1, c)]
    1.14 -        l.append((pow(d, -3), c))
    1.15 -        total += pow(d, -3)
    1.16 -    return [(d / total, c) for d, c in l]
    1.17 +def nearest(rgb, values):
    1.18 +    l = [(distance(rgb, value), value) for value in values]
    1.19 +    l.sort()
    1.20 +    return l[0][1]
    1.21 +
    1.22 +def scale(rgb):
    1.23 +    return tuple(map(lambda x: x / 255.0, rgb))
    1.24 +
    1.25 +def invert(srgb):
    1.26 +    return tuple(map(lambda x: 1.0 - x, srgb))
    1.27 +
    1.28 +def combination(rgb):
    1.29 +    rgb = scale(rgb)
    1.30 +    rgbi = invert(rgb)
    1.31 +    pairs = zip(rgbi, rgb)
    1.32 +    d = []
    1.33 +    for corner in corners:
    1.34 +        rs, gs, bs = scale(corner)
    1.35 +        d.append((pairs[0][int(rs)] * pairs[1][int(gs)] * pairs[2][int(bs)], corner))
    1.36 +    return d
    1.37  
    1.38 -def pattern(rgb, values=None):
    1.39 -    l = distribution(rgb, values or corners)
    1.40 +def combine(d):
    1.41 +    out = [0, 0, 0]
    1.42 +    for v, rgb in d:
    1.43 +        out[0] += v * rgb[0]
    1.44 +        out[1] += v * rgb[1]
    1.45 +        out[2] += v * rgb[2]
    1.46 +    return out
    1.47 +
    1.48 +"""
    1.49 +r(R - K)
    1.50 +r(Y - G)
    1.51 +r(M - B)
    1.52 +r(W - C)
    1.53 +g(G - K)
    1.54 +g(Y - R)
    1.55 +g(C - B)
    1.56 +g(W - M)
    1.57 +b(B - K)
    1.58 +b(M - R)
    1.59 +b(C - G)
    1.60 +b(W - Y)
    1.61 +
    1.62 +b(g(r(W - C) - r(M - B)) - g(r(Y - G) - r(R - K)))
    1.63 +b(r(g(W - M) - g(C - B)) - r(g(Y - R) - g(G - K)))
    1.64 +
    1.65 +b(g(rW + riC) + gi(rM + riB)) + bi(g(rY + riG) + gi(rR + riK))
    1.66 +b(r(gW + giM) + ri(gC + giB)) + bi(r(gY + giR) + ri(gG + giK))
    1.67 +
    1.68 +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.69 +...
    1.70 +"""
    1.71 +
    1.72 +def pattern(rgb):
    1.73 +    l = combination(rgb)
    1.74      l.sort(reverse=True)
    1.75      return l
    1.76  
    1.77 -def get_value(rgb, values=None):
    1.78 +def get_value(rgb):
    1.79      choose = random()
    1.80      threshold = 0
    1.81 -    for f, c in pattern(rgb, values):
    1.82 +    for f, c in pattern(rgb):
    1.83          threshold += f
    1.84          if choose < threshold:
    1.85              return c
    1.86 @@ -128,7 +170,7 @@
    1.87  
    1.88              # Sum the colour probabilities.
    1.89  
    1.90 -            for f, value in distribution(rgb):
    1.91 +            for f, value in combination(rgb):
    1.92                  if not c.has_key(value):
    1.93                      c[value] = f
    1.94                  else:
    1.95 @@ -142,11 +184,11 @@
    1.96          most = [value for n, value in c[:4]]
    1.97          least = [value for n, value in c[4:]]
    1.98  
    1.99 -        if least:
   1.100 -            if (0, 0, 0) in least[:2]:
   1.101 -                replace((0, 0, 0), most)
   1.102 -            if (255, 255, 255) in least[:2]:
   1.103 -                replace((255, 255, 255), most)
   1.104 +        #if least:
   1.105 +        #    if (0, 0, 0) in least[:2]:
   1.106 +        #        replace((0, 0, 0), most)
   1.107 +        #    if (255, 255, 255) in least[:2]:
   1.108 +        #        replace((255, 255, 255), most)
   1.109  
   1.110          for x in range(0, width):
   1.111              rgb = im.getpixel((x, y))
   1.112 @@ -156,8 +198,7 @@
   1.113  
   1.114              value = get_value(rgb)
   1.115              if value in least:
   1.116 -                rgb = im.getpixel((x, y))
   1.117 -                value = get_value(value, most)
   1.118 +                value = nearest(value, most)
   1.119  
   1.120              im.putpixel((x, y), value)
   1.121