PaletteOptimiser

Change of optimiser.py

49:1036d8b98d85
optimiser.py
     1.1 --- a/optimiser.py	Tue Oct 06 14:31:54 2015 +0200
     1.2 +++ b/optimiser.py	Tue Oct 06 17:33:36 2015 +0200
     1.3 @@ -13,6 +13,12 @@
     1.4      (0, 0, 255), (255, 0, 255), (0, 255, 255), (255, 255, 255)
     1.5      ]
     1.6  
     1.7 +def within(v, lower, upper):
     1.8 +    return min(max(v, lower), upper)
     1.9 +
    1.10 +def clip(v):
    1.11 +    return within(v, 0, 255)
    1.12 +
    1.13  def distance(rgb1, rgb2):
    1.14      r1, g1, b1 = rgb1
    1.15      r2, g2, b2 = rgb2
    1.16 @@ -104,12 +110,28 @@
    1.17  def saturate_value(x, exp):
    1.18      return int(127.5 + sign(x - 127.5) * 127.5 * pow(abs(x - 127.5) / 127.5, exp))
    1.19  
    1.20 -def replace(value, values):
    1.21 -    if value not in values:
    1.22 -        for i, v in list(enumerate(values))[::-1]:
    1.23 -            if v != value:
    1.24 -                values[i] = value
    1.25 -                return
    1.26 +def amplify_rgb(rgb, exp):
    1.27 +    return tuple([amplify_value(x, exp) for x in rgb])
    1.28 +
    1.29 +def amplify_value(x, exp):
    1.30 +    return int(pow(x / 255.0, exp) * 255.0)
    1.31 +
    1.32 +def get_colours(im, width, y):
    1.33 +    c = {}
    1.34 +    for x in range(0, width):
    1.35 +        rgb = im.getpixel((x, y))
    1.36 +
    1.37 +        # Sum the colour probabilities.
    1.38 +
    1.39 +        for f, value in combination(rgb):
    1.40 +            if not c.has_key(value):
    1.41 +                c[value] = f
    1.42 +            else:
    1.43 +                c[value] += f
    1.44 +
    1.45 +    c = [(n/width, value) for value, n in c.items()]
    1.46 +    c.sort(reverse=True)
    1.47 +    return c
    1.48  
    1.49  def test():
    1.50      size = 512
    1.51 @@ -159,9 +181,10 @@
    1.52      rotate = "-r" in sys.argv[3:]
    1.53      saturate = sys.argv[3:].count("-s")
    1.54      desaturate = sys.argv[3:].count("-d")
    1.55 +    darken = sys.argv[3:].count("-D")
    1.56 +    brighten = sys.argv[3:].count("-B")
    1.57      preview = "-p" in sys.argv[3:]
    1.58      square = "-2" in sys.argv[3:] and square or (lambda x: x)
    1.59 -    randomise = "-R" in sys.argv[3:]
    1.60  
    1.61      x = EXIF.process_file(open(input_filename))
    1.62      im = PIL.Image.open(input_filename).convert("RGB")
    1.63 @@ -169,30 +192,18 @@
    1.64  
    1.65      width, height = im.size
    1.66  
    1.67 -    colours = []
    1.68 -
    1.69 -    for y in range(0, height):
    1.70 -        c = {}
    1.71 -        for x in range(0, width):
    1.72 -            rgb = im.getpixel((x, y))
    1.73 -
    1.74 -            # Saturate if requested.
    1.75 +    if saturate or desaturate or darken or brighten:
    1.76 +        for y in range(0, height):
    1.77 +            for x in range(0, width):
    1.78 +                if saturate or desaturate:
    1.79 +                    rgb = im.getpixel((x, y))
    1.80 +                    rgb = saturate_rgb(rgb, saturate and math.pow(0.5, saturate) or math.pow(2, desaturate))
    1.81 +                    im.putpixel((x, y), rgb)
    1.82  
    1.83 -            if saturate or desaturate:
    1.84 -                rgb = saturate_rgb(rgb, saturate and math.pow(0.5, saturate) or math.pow(2, desaturate))
    1.85 -                im.putpixel((x, y), rgb)
    1.86 -
    1.87 -            # Sum the colour probabilities.
    1.88 -
    1.89 -            for f, value in combination(rgb):
    1.90 -                if not c.has_key(value):
    1.91 -                    c[value] = f
    1.92 -                else:
    1.93 -                    c[value] += f
    1.94 -
    1.95 -        c = [(n/width, value) for value, n in c.items()]
    1.96 -        c.sort(reverse=True)
    1.97 -        colours.append(c)
    1.98 +                if darken or brighten:
    1.99 +                    rgb = im.getpixel((x, y))
   1.100 +                    rgb = amplify_rgb(rgb, brighten and math.pow(0.5, brighten) or math.pow(2, darken))
   1.101 +                    im.putpixel((x, y), rgb)
   1.102  
   1.103      if preview:
   1.104          imp = im.copy()
   1.105 @@ -203,27 +214,21 @@
   1.106                  imp.putpixel((x, y), value)
   1.107          imp.save(preview_filename)
   1.108  
   1.109 -    for y, c in enumerate(colours):
   1.110 +    for y in range(0, height):
   1.111 +        c = get_colours(im, width, y)
   1.112          most = [value for n, value in c[:4]]
   1.113          least = [value for n, value in c[4:]]
   1.114  
   1.115 -        if least and randomise:
   1.116 -            switched = []
   1.117 -            for j in 1, 2:
   1.118 -                i = randrange(0, 4)
   1.119 -                n, value = c[i]
   1.120 -                if n < 0.1:
   1.121 -                    switched.append(c[i])
   1.122 -                    del c[i]
   1.123 -            c += switched
   1.124 -            most = [value for n, value in c[:4]]
   1.125 -            least = [value for n, value in c[4:]]
   1.126 -
   1.127          for x in range(0, width):
   1.128              rgb = im.getpixel((x, y))
   1.129              value = get_value(rgb, most)
   1.130              im.putpixel((x, y), value)
   1.131  
   1.132 +            if y < height - 1:
   1.133 +                rgbn = im.getpixel((x, y+1))
   1.134 +                rgbn = tuple(map(lambda i: clip(i[0] + i[1] - i[2]), zip(rgbn, rgb, value)))
   1.135 +                im.putpixel((x, y+1), rgbn)
   1.136 +
   1.137      im.save(output_filename)
   1.138  
   1.139  # vim: tabstop=4 expandtab shiftwidth=4