# HG changeset patch # User Paul Boddie # Date 1443883937 -7200 # Node ID 9060af8f5ef50aa1c76dc398594f0b3353a1e1d1 # Parent da4132364cfd8e838b5020c2a0f04375d87813ec Adopt a more thorough model of colour selection. diff -r da4132364cfd -r 9060af8f5ef5 optimiser.py --- a/optimiser.py Sat Oct 03 01:32:26 2015 +0200 +++ b/optimiser.py Sat Oct 03 16:52:17 2015 +0200 @@ -18,26 +18,68 @@ r2, g2, b2 = rgb2 return math.sqrt(pow(r1 - r2, 2) + pow(g1 - g2, 2) + pow(b1 - b2, 2)) -def distribution(rgb, values=None): - l = [] - total = 0 - for c in values or corners: - d = distance(rgb, c) - if d == 0: - return [(1, c)] - l.append((pow(d, -3), c)) - total += pow(d, -3) - return [(d / total, c) for d, c in l] +def nearest(rgb, values): + l = [(distance(rgb, value), value) for value in values] + l.sort() + return l[0][1] + +def scale(rgb): + return tuple(map(lambda x: x / 255.0, rgb)) + +def invert(srgb): + return tuple(map(lambda x: 1.0 - x, srgb)) + +def combination(rgb): + rgb = scale(rgb) + rgbi = invert(rgb) + pairs = zip(rgbi, rgb) + d = [] + for corner in corners: + rs, gs, bs = scale(corner) + d.append((pairs[0][int(rs)] * pairs[1][int(gs)] * pairs[2][int(bs)], corner)) + return d -def pattern(rgb, values=None): - l = distribution(rgb, values or corners) +def combine(d): + out = [0, 0, 0] + for v, rgb in d: + out[0] += v * rgb[0] + out[1] += v * rgb[1] + out[2] += v * rgb[2] + return out + +""" +r(R - K) +r(Y - G) +r(M - B) +r(W - C) +g(G - K) +g(Y - R) +g(C - B) +g(W - M) +b(B - K) +b(M - R) +b(C - G) +b(W - Y) + +b(g(r(W - C) - r(M - B)) - g(r(Y - G) - r(R - K))) +b(r(g(W - M) - g(C - B)) - r(g(Y - R) - g(G - K))) + +b(g(rW + riC) + gi(rM + riB)) + bi(g(rY + riG) + gi(rR + riK)) +b(r(gW + giM) + ri(gC + giB)) + bi(r(gY + giR) + ri(gG + giK)) + +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) +... +""" + +def pattern(rgb): + l = combination(rgb) l.sort(reverse=True) return l -def get_value(rgb, values=None): +def get_value(rgb): choose = random() threshold = 0 - for f, c in pattern(rgb, values): + for f, c in pattern(rgb): threshold += f if choose < threshold: return c @@ -128,7 +170,7 @@ # Sum the colour probabilities. - for f, value in distribution(rgb): + for f, value in combination(rgb): if not c.has_key(value): c[value] = f else: @@ -142,11 +184,11 @@ most = [value for n, value in c[:4]] least = [value for n, value in c[4:]] - if least: - if (0, 0, 0) in least[:2]: - replace((0, 0, 0), most) - if (255, 255, 255) in least[:2]: - replace((255, 255, 255), most) + #if least: + # if (0, 0, 0) in least[:2]: + # replace((0, 0, 0), most) + # if (255, 255, 255) in least[:2]: + # replace((255, 255, 255), most) for x in range(0, width): rgb = im.getpixel((x, y)) @@ -156,8 +198,7 @@ value = get_value(rgb) if value in least: - rgb = im.getpixel((x, y)) - value = get_value(value, most) + value = nearest(value, most) im.putpixel((x, y), value)