1.1 --- a/optimiser.py Fri Oct 09 22:16:49 2015 +0200
1.2 +++ b/optimiser.py Fri Oct 09 23:48:21 2015 +0200
1.3 @@ -21,9 +21,6 @@
1.4 """
1.5
1.6 from random import random, randrange
1.7 -from os.path import split, splitext
1.8 -import EXIF
1.9 -import PIL.Image
1.10 import itertools
1.11 import math
1.12 import sys
1.13 @@ -208,49 +205,16 @@
1.14 all.sort(reverse=True)
1.15 return [l for total, l in all]
1.16
1.17 -def test():
1.18 -
1.19 - "Generate slices of the colour cube."
1.20 +def test_slice(im, size, r):
1.21 + for g in range(0, size):
1.22 + for b in range(0, size):
1.23 + value = get_value((r, (g * 256) / size, (b * 256 / size)))
1.24 + im.putpixel((g, b), value)
1.25
1.26 - size = 512
1.27 - for r in (0, 63, 127, 191, 255):
1.28 - im = PIL.Image.new("RGB", (size, size))
1.29 - for g in range(0, size):
1.30 - for b in range(0, size):
1.31 - value = get_value((r, (g * 256) / size, (b * 256 / size)))
1.32 - im.putpixel((g, b), value)
1.33 - im.save("rgb%d.png" % r)
1.34 -
1.35 -def test_flat(rgb):
1.36 -
1.37 - "Generate a flat image for the colour 'rgb'."
1.38 -
1.39 - size = 64
1.40 - im = PIL.Image.new("RGB", (size, size))
1.41 +def test_flat_slice(im, size, rgb):
1.42 for y in range(0, size):
1.43 for x in range(0, size):
1.44 im.putpixel((x, y), get_value(rgb))
1.45 - im.save("rgb%02d%02d%02d.png" % rgb)
1.46 -
1.47 -def rotate_and_scale(exif, im, width, height, rotate):
1.48 -
1.49 - """
1.50 - Using the given 'exif' information, rotate and scale image 'im' given the
1.51 - indicated 'width' and 'height' constraints and any explicit 'rotate'
1.52 - indication. The returned image will be within the given 'width' and
1.53 - 'height', filling either or both, and preserve its original aspect ratio.
1.54 - """
1.55 -
1.56 - if rotate or exif and exif["Image Orientation"].values == [6L]:
1.57 - im = im.rotate(270)
1.58 -
1.59 - w, h = im.size
1.60 - if w > h:
1.61 - height = (width * h) / w
1.62 - else:
1.63 - width = (height * w) / h
1.64 -
1.65 - return im.resize((width, height))
1.66
1.67 def count_colours(im, colours):
1.68
1.69 @@ -263,9 +227,7 @@
1.70 width, height = im.size
1.71
1.72 for y in range(0, height):
1.73 - l = set()
1.74 - for x in range(0, width):
1.75 - l.add(im.getpixel((x, y)))
1.76 + l = set(im.getdata()[y * width:(y+1) * width])
1.77 if len(l) > colours:
1.78 return (y, l)
1.79 return None
1.80 @@ -344,101 +306,44 @@
1.81 rgbn = tuple(map(lambda i: clip(i[0] + (i[1] - i[2]) / 2.0), zip(rgbn, rgb, value)))
1.82 im.putpixel((x, y+1), rgbn)
1.83
1.84 -def get_float(options, flag):
1.85 - try:
1.86 - i = options.index(flag)
1.87 - if i+1 < len(options) and options[i+1].isdigit():
1.88 - return float(options[i+1])
1.89 - else:
1.90 - return 1.0
1.91 - except ValueError:
1.92 - return 0.0
1.93 +class SimpleImage:
1.94 +
1.95 + "An image behaving like PIL.Image."
1.96 +
1.97 + def __init__(self, data, size):
1.98 + self.data = data
1.99 + self.width, self.height = self.size = size
1.100 +
1.101 + def copy(self):
1.102 + return SimpleImage(self.data[:], self.size)
1.103
1.104 -# Main program.
1.105 + def getpixel(self, xy):
1.106 + x, y = xy
1.107 + return self.data[y * self.width + x]
1.108 +
1.109 + def putpixel(self, xy, value):
1.110 + x, y = xy
1.111 + self.data[y * self.width + x] = value
1.112 +
1.113 + def getdata(self):
1.114 + return self.data
1.115 +
1.116 +# Test program.
1.117
1.118 if __name__ == "__main__":
1.119 -
1.120 - # Test options.
1.121 -
1.122 - if "--test" in sys.argv:
1.123 - test()
1.124 - sys.exit(0)
1.125 - elif "--test-flat" in sys.argv:
1.126 - test_flat((120, 40, 60))
1.127 - sys.exit(0)
1.128 - elif "--help" in sys.argv:
1.129 - print >>sys.stderr, """\
1.130 -Usage: %s <input filename> <output filename> [ <options> ]
1.131 -
1.132 -Options are...
1.133 + data = [(0, 0, 0)] * 1024
1.134 + size = (32, 32)
1.135
1.136 --s - Saturate the input image (can be followed by a float, default 1.0)
1.137 --d - Desaturate the input image (can be followed by a float, default 1.0)
1.138 --D - Darken the input image (can be followed by a float, default 1.0)
1.139 --B - Brighten the input image (can be followed by a float, default 1.0)
1.140 -
1.141 --r - Rotate the input image clockwise
1.142 --p - Generate a separate preview image
1.143 --h - Make the preview image with half horizontal resolution (MODE 2)
1.144 --v - Verify the output image (loaded if -n is given)
1.145 --n - Generate no output image
1.146 -""" % split(sys.argv[0])[1]
1.147 - sys.exit(1)
1.148 -
1.149 - width = 320
1.150 - height = 256
1.151 -
1.152 - input_filename, output_filename = sys.argv[1:3]
1.153 - basename, ext = splitext(output_filename)
1.154 - preview_filename = "".join([basename + "_preview", ext])
1.155 -
1.156 - options = sys.argv[3:]
1.157 -
1.158 - # Preprocessing options that can be repeated for extra effect.
1.159 + im = SimpleImage(data, size)
1.160
1.161 - saturate = get_float(options, "-s")
1.162 - desaturate = get_float(options, "-d")
1.163 - darken = get_float(options, "-D")
1.164 - brighten = get_float(options, "-B")
1.165 -
1.166 - # General output options.
1.167 -
1.168 - rotate = "-r" in options
1.169 - preview = "-p" in options
1.170 - half_resolution_preview = "-h" in options
1.171 - verify = "-v" in options
1.172 - no_normal_output = "-n" in options
1.173 - make_image = not no_normal_output
1.174 -
1.175 - # Load the input image if requested.
1.176 -
1.177 - if make_image or preview:
1.178 - exif = EXIF.process_file(open(input_filename))
1.179 - im = PIL.Image.open(input_filename).convert("RGB")
1.180 - im = rotate_and_scale(exif, im, width, height, rotate)
1.181 + process_image(im, 1.0, 0.0, 1.0, 0.0)
1.182 + imp = preview_image(im, False)
1.183 + convert_image(im)
1.184
1.185 - process_image(im, saturate, desaturate, darken, brighten)
1.186 -
1.187 - # Generate a preview if requested.
1.188 -
1.189 - if preview:
1.190 - preview_image(im, half_resolution_preview).save(preview_filename)
1.191 -
1.192 - # Generate an output image if requested.
1.193 + test_im = SimpleImage(data, size)
1.194 + test_slice(test_im, 32, 0)
1.195
1.196 - if make_image:
1.197 - convert_image(im)
1.198 - im.save(output_filename)
1.199 -
1.200 - # Verify the output image (which may be loaded) if requested.
1.201 -
1.202 - if verify:
1.203 - if no_normal_output:
1.204 - im = PIL.Image.open(output_filename).convert("RGB")
1.205 -
1.206 - result = count_colours(im, 4)
1.207 - if result is not None:
1.208 - y, colours = result
1.209 - print "Image %s: row %d has the following colours: %s" % (output_filename, y, "; ".join([repr(c) for c in colours]))
1.210 + test_flat_im = SimpleImage(data, size)
1.211 + test_flat_slice(test_flat_im, 32, (200, 100, 50))
1.212
1.213 # vim: tabstop=4 expandtab shiftwidth=4