PaletteOptimiser

Changeset

60:01d3243e1374
2015-10-09 Paul Boddie raw files shortlog changelog graph Attempt to find the next best combination of colours when some pixel values cannot be represented.
optimiser.py (file)
     1.1 --- a/optimiser.py	Thu Oct 08 23:45:40 2015 +0200
     1.2 +++ b/optimiser.py	Fri Oct 09 00:01:29 2015 +0200
     1.3 @@ -24,6 +24,7 @@
     1.4  from os.path import split, splitext
     1.5  import EXIF
     1.6  import PIL.Image
     1.7 +import itertools
     1.8  import math
     1.9  import sys
    1.10  
    1.11 @@ -137,21 +138,25 @@
    1.12      specified 'chosen' colours.
    1.13      """
    1.14  
    1.15 -    l = [(f, value) for f, value in combination(rgb) if value in chosen]
    1.16 +    l = [(f, value) for f, value in combination(rgb) if not chosen or value in chosen]
    1.17      l.sort(reverse=True)
    1.18      return l
    1.19  
    1.20 -def get_value(rgb, chosen=None):
    1.21 +def get_value(rgb, chosen=None, fail=False):
    1.22  
    1.23      """
    1.24      Get an output colour for 'rgb', optionally limited to any specified 'chosen'
    1.25 -    colours.
    1.26 +    colours. If 'fail' is set to a true value, return None if the colour cannot
    1.27 +    be expressed using any of the chosen colours.
    1.28      """
    1.29  
    1.30      l = pattern(rgb, chosen)
    1.31      limit = sum([f for f, c in l])
    1.32      if not limit:
    1.33 -        return l[randrange(0, len(l))][1]
    1.34 +        if fail:
    1.35 +            return None
    1.36 +        else:
    1.37 +            return l[randrange(0, len(l))][1]
    1.38  
    1.39      choose = random() * limit
    1.40      threshold = 0
    1.41 @@ -201,6 +206,22 @@
    1.42      c.sort(reverse=True)
    1.43      return c
    1.44  
    1.45 +def get_combinations(c, n):
    1.46 +
    1.47 +    """
    1.48 +    Get combinations of colours from 'c' of size 'n' in decreasing order of
    1.49 +    probability.
    1.50 +    """
    1.51 +
    1.52 +    all = []
    1.53 +    for l in itertools.combinations(c, n):
    1.54 +        total = 0
    1.55 +        for f, value in l:
    1.56 +            total += f
    1.57 +        all.append((total, l))
    1.58 +    all.sort(reverse=True)
    1.59 +    return [l for total, l in all]
    1.60 +
    1.61  def test():
    1.62  
    1.63      "Generate slices of the colour cube."
    1.64 @@ -366,8 +387,18 @@
    1.65      if make_image:
    1.66          for y in range(0, height):
    1.67              c = get_colours(im, y)
    1.68 -            most = [value for n, value in c[:4]]
    1.69 -            least = [value for n, value in c[4:]]
    1.70 +
    1.71 +            for l in get_combinations(c, 4):
    1.72 +                most = [value for f, value in l]
    1.73 +                for x in range(0, width):
    1.74 +                    rgb = im.getpixel((x, y))
    1.75 +                    value = get_value(rgb, most, True)
    1.76 +                    if value is None:
    1.77 +                        break # try next combination
    1.78 +                else:
    1.79 +                    break # use this combination
    1.80 +            else:
    1.81 +                most = [value for f, value in c[:4]] # use the first four
    1.82  
    1.83              for x in range(0, width):
    1.84                  rgb = im.getpixel((x, y))