PaletteOptimiser

Changeset

70:5b3e85002c10
2015-10-09 Paul Boddie raw files shortlog changelog graph Moved various activities to their own functions.
optimiser.py (file)
     1.1 --- a/optimiser.py	Fri Oct 09 21:58:23 2015 +0200
     1.2 +++ b/optimiser.py	Fri Oct 09 22:16:49 2015 +0200
     1.3 @@ -261,6 +261,7 @@
     1.4      """
     1.5  
     1.6      width, height = im.size
     1.7 +
     1.8      for y in range(0, height):
     1.9          l = set()
    1.10          for x in range(0, width):
    1.11 @@ -269,6 +270,80 @@
    1.12              return (y, l)
    1.13      return None
    1.14  
    1.15 +def process_image(im, saturate, desaturate, darken, brighten):
    1.16 +
    1.17 +    """
    1.18 +    Process image 'im' using the given options: 'saturate', 'desaturate',
    1.19 +    'darken', 'brighten'.
    1.20 +    """
    1.21 +
    1.22 +    width, height = im.size
    1.23 +
    1.24 +    if saturate or desaturate or darken or brighten:
    1.25 +        for y in range(0, height):
    1.26 +            for x in range(0, width):
    1.27 +                rgb = im.getpixel((x, y))
    1.28 +                if saturate or desaturate:
    1.29 +                    rgb = saturate_rgb(rgb, saturate and 0.5 / saturate or 2 * desaturate)
    1.30 +                if darken or brighten:
    1.31 +                    rgb = amplify_rgb(rgb, brighten and 0.5 / brighten or 2 * darken)
    1.32 +                im.putpixel((x, y), rgb)
    1.33 +
    1.34 +def preview_image(im, half_resolution_preview=False):
    1.35 +
    1.36 +    "Return a preview copy of image 'im'."
    1.37 +
    1.38 +    width, height = im.size
    1.39 +
    1.40 +    imp = im.copy()
    1.41 +    step = half_resolution_preview and 2 or 1
    1.42 +
    1.43 +    for y in range(0, height):
    1.44 +        for x in range(0, width, step):
    1.45 +            rgb = imp.getpixel((x, y))
    1.46 +            value = get_value(rgb)
    1.47 +            imp.putpixel((x, y), value)
    1.48 +            if half_resolution_preview:
    1.49 +                imp.putpixel((x+1, y), value)
    1.50 +
    1.51 +    return imp
    1.52 +
    1.53 +def convert_image(im):
    1.54 +
    1.55 +    "Convert image 'im' to an appropriate output representation."
    1.56 +
    1.57 +    width, height = im.size
    1.58 +
    1.59 +    for y in range(0, height):
    1.60 +        c = get_colours(im, y)
    1.61 +
    1.62 +        for l in get_combinations(c, 4):
    1.63 +            most = [value for f, value in l]
    1.64 +            for x in range(0, width):
    1.65 +                rgb = im.getpixel((x, y))
    1.66 +                value = get_value(rgb, most, True)
    1.67 +                if value is None:
    1.68 +                    break # try next combination
    1.69 +            else:
    1.70 +                break # use this combination
    1.71 +        else:
    1.72 +            most = [value for f, value in c[:4]] # use the first four
    1.73 +
    1.74 +        for x in range(0, width):
    1.75 +            rgb = im.getpixel((x, y))
    1.76 +            value = get_value(rgb, most)
    1.77 +            im.putpixel((x, y), value)
    1.78 +
    1.79 +            if x < width - 1:
    1.80 +                rgbn = im.getpixel((x+1, y))
    1.81 +                rgbn = tuple(map(lambda i: clip(i[0] + (i[1] - i[2]) / 4.0), zip(rgbn, rgb, value)))
    1.82 +                im.putpixel((x+1, y), rgbn)
    1.83 +
    1.84 +            if y < height - 1:
    1.85 +                rgbn = im.getpixel((x, y+1))
    1.86 +                rgbn = tuple(map(lambda i: clip(i[0] + (i[1] - i[2]) / 2.0), zip(rgbn, rgb, value)))
    1.87 +                im.putpixel((x, y+1), rgbn)
    1.88 +
    1.89  def get_float(options, flag):
    1.90      try:
    1.91          i = options.index(flag)
    1.92 @@ -342,66 +417,17 @@
    1.93          im = PIL.Image.open(input_filename).convert("RGB")
    1.94          im = rotate_and_scale(exif, im, width, height, rotate)
    1.95  
    1.96 -        width, height = im.size
    1.97 -
    1.98 -        if saturate or desaturate or darken or brighten:
    1.99 -            for y in range(0, height):
   1.100 -                for x in range(0, width):
   1.101 -                    rgb = im.getpixel((x, y))
   1.102 -                    if saturate or desaturate:
   1.103 -                        rgb = saturate_rgb(rgb, saturate and 0.5 / saturate or 2 * desaturate)
   1.104 -                    if darken or brighten:
   1.105 -                        rgb = amplify_rgb(rgb, brighten and 0.5 / brighten or 2 * darken)
   1.106 -                    im.putpixel((x, y), rgb)
   1.107 +        process_image(im, saturate, desaturate, darken, brighten)
   1.108  
   1.109      # Generate a preview if requested.
   1.110  
   1.111      if preview:
   1.112 -        imp = im.copy()
   1.113 -        step = half_resolution_preview and 2 or 1
   1.114 -        for y in range(0, height):
   1.115 -            for x in range(0, width, step):
   1.116 -                rgb = imp.getpixel((x, y))
   1.117 -                value = get_value(rgb)
   1.118 -                imp.putpixel((x, y), value)
   1.119 -                if half_resolution_preview:
   1.120 -                    imp.putpixel((x+1, y), value)
   1.121 -
   1.122 -        imp.save(preview_filename)
   1.123 +        preview_image(im, half_resolution_preview).save(preview_filename)
   1.124  
   1.125      # Generate an output image if requested.
   1.126  
   1.127      if make_image:
   1.128 -        for y in range(0, height):
   1.129 -            c = get_colours(im, y)
   1.130 -
   1.131 -            for l in get_combinations(c, 4):
   1.132 -                most = [value for f, value in l]
   1.133 -                for x in range(0, width):
   1.134 -                    rgb = im.getpixel((x, y))
   1.135 -                    value = get_value(rgb, most, True)
   1.136 -                    if value is None:
   1.137 -                        break # try next combination
   1.138 -                else:
   1.139 -                    break # use this combination
   1.140 -            else:
   1.141 -                most = [value for f, value in c[:4]] # use the first four
   1.142 -
   1.143 -            for x in range(0, width):
   1.144 -                rgb = im.getpixel((x, y))
   1.145 -                value = get_value(rgb, most)
   1.146 -                im.putpixel((x, y), value)
   1.147 -
   1.148 -                if x < width - 1:
   1.149 -                    rgbn = im.getpixel((x+1, y))
   1.150 -                    rgbn = tuple(map(lambda i: clip(i[0] + (i[1] - i[2]) / 4.0), zip(rgbn, rgb, value)))
   1.151 -                    im.putpixel((x+1, y), rgbn)
   1.152 -
   1.153 -                if y < height - 1:
   1.154 -                    rgbn = im.getpixel((x, y+1))
   1.155 -                    rgbn = tuple(map(lambda i: clip(i[0] + (i[1] - i[2]) / 2.0), zip(rgbn, rgb, value)))
   1.156 -                    im.putpixel((x, y+1), rgbn)
   1.157 -
   1.158 +        convert_image(im)
   1.159          im.save(output_filename)
   1.160  
   1.161      # Verify the output image (which may be loaded) if requested.