# HG changeset patch # User Paul Boddie # Date 1444341689 -7200 # Node ID 01d3243e1374045430cb063eb8e623fe2633ceb3 # Parent a64e7a0a3d333c9be11d441671036655fdee7b7e Attempt to find the next best combination of colours when some pixel values cannot be represented. diff -r a64e7a0a3d33 -r 01d3243e1374 optimiser.py --- a/optimiser.py Thu Oct 08 23:45:40 2015 +0200 +++ b/optimiser.py Fri Oct 09 00:01:29 2015 +0200 @@ -24,6 +24,7 @@ from os.path import split, splitext import EXIF import PIL.Image +import itertools import math import sys @@ -137,21 +138,25 @@ specified 'chosen' colours. """ - l = [(f, value) for f, value in combination(rgb) if value in chosen] + l = [(f, value) for f, value in combination(rgb) if not chosen or value in chosen] l.sort(reverse=True) return l -def get_value(rgb, chosen=None): +def get_value(rgb, chosen=None, fail=False): """ Get an output colour for 'rgb', optionally limited to any specified 'chosen' - colours. + colours. If 'fail' is set to a true value, return None if the colour cannot + be expressed using any of the chosen colours. """ l = pattern(rgb, chosen) limit = sum([f for f, c in l]) if not limit: - return l[randrange(0, len(l))][1] + if fail: + return None + else: + return l[randrange(0, len(l))][1] choose = random() * limit threshold = 0 @@ -201,6 +206,22 @@ c.sort(reverse=True) return c +def get_combinations(c, n): + + """ + Get combinations of colours from 'c' of size 'n' in decreasing order of + probability. + """ + + all = [] + for l in itertools.combinations(c, n): + total = 0 + for f, value in l: + total += f + all.append((total, l)) + all.sort(reverse=True) + return [l for total, l in all] + def test(): "Generate slices of the colour cube." @@ -366,8 +387,18 @@ if make_image: for y in range(0, height): c = get_colours(im, y) - most = [value for n, value in c[:4]] - least = [value for n, value in c[4:]] + + for l in get_combinations(c, 4): + most = [value for f, value in l] + for x in range(0, width): + rgb = im.getpixel((x, y)) + value = get_value(rgb, most, True) + if value is None: + break # try next combination + else: + break # use this combination + else: + most = [value for f, value in c[:4]] # use the first four for x in range(0, width): rgb = im.getpixel((x, y))