1.1 --- a/optimiser.py Sat Oct 10 23:54:55 2015 +0200
1.2 +++ b/optimiser.py Sun Oct 11 15:19:18 2015 +0200
1.3 @@ -294,26 +294,7 @@
1.4 rgb = amplify_rgb(rgb, brighten and 0.5 / brighten or 2 * darken)
1.5 im.putpixel((x, y), rgb)
1.6
1.7 -def preview_image(im, half_resolution_preview=False):
1.8 -
1.9 - "Return a preview copy of image 'im'."
1.10 -
1.11 - width, height = im.size
1.12 -
1.13 - imp = im.copy()
1.14 - step = half_resolution_preview and 2 or 1
1.15 -
1.16 - for y in range(0, height):
1.17 - for x in range(0, width, step):
1.18 - rgb = imp.getpixel((x, y))
1.19 - value = get_value(rgb)
1.20 - imp.putpixel((x, y), value)
1.21 - if half_resolution_preview:
1.22 - imp.putpixel((x+1, y), value)
1.23 -
1.24 - return imp
1.25 -
1.26 -def convert_image(im):
1.27 +def convert_image(im, colours):
1.28
1.29 "Convert image 'im' to an appropriate output representation."
1.30
1.31 @@ -322,7 +303,7 @@
1.32 for y in range(0, height):
1.33 c = get_colours(im, y)
1.34
1.35 - for l in get_combinations(c, 4):
1.36 + for l in get_combinations(c, colours):
1.37 most = [value for f, value in l]
1.38 for x in range(0, width):
1.39 rgb = im.getpixel((x, y))
1.40 @@ -332,7 +313,7 @@
1.41 else:
1.42 break # use this combination
1.43 else:
1.44 - most = [value for f, value in c[:4]] # use the first four
1.45 + most = [value for f, value in c[:colours]] # use the first colours
1.46
1.47 for x in range(0, width):
1.48 rgb = im.getpixel((x, y))
1.49 @@ -357,15 +338,23 @@
1.50 )
1.51 im.putpixel((x, y+1), rgbn)
1.52
1.53 -def get_float(options, flag):
1.54 +def get_parameter(options, flag, conversion, default, missing):
1.55 +
1.56 + """
1.57 + From 'options', return any parameter following the given 'flag', applying
1.58 + the 'conversion' which has the given 'default' if no valid parameter is
1.59 + found, or returning the given 'missing' value if the flag does not appear at
1.60 + all.
1.61 + """
1.62 +
1.63 try:
1.64 i = options.index(flag)
1.65 try:
1.66 - return float(options[i+1])
1.67 + return conversion(options[i+1])
1.68 except (IndexError, ValueError):
1.69 - return 1.0
1.70 + return default
1.71 except ValueError:
1.72 - return 0.0
1.73 + return missing
1.74
1.75 # Main program.
1.76
1.77 @@ -385,10 +374,13 @@
1.78
1.79 Options are...
1.80
1.81 --s - Saturate the input image (can be followed by a float, default 1.0)
1.82 --d - Desaturate the input image (can be followed by a float, default 1.0)
1.83 --D - Darken the input image (can be followed by a float, default 1.0)
1.84 --B - Brighten the input image (can be followed by a float, default 1.0)
1.85 +-W - Indicate the output width (default is 320)
1.86 +-C - Number of colours per scanline (default is 4)
1.87 +
1.88 +-s - Saturate the input image (optional float, 1.0 if unspecified)
1.89 +-d - Desaturate the input image (optional float, 1.0 if unspecified)
1.90 +-D - Darken the input image (optional float, 1.0 if unspecified)
1.91 +-B - Brighten the input image (optional float, 1.0 if unspecified)
1.92
1.93 -r - Rotate the input image clockwise
1.94 -p - Generate a separate preview image
1.95 @@ -398,7 +390,7 @@
1.96 """ % split(sys.argv[0])[1]
1.97 sys.exit(1)
1.98
1.99 - width = 320
1.100 + base_width = 320
1.101 height = 256
1.102
1.103 input_filename, output_filename = sys.argv[1:3]
1.104 @@ -407,12 +399,17 @@
1.105
1.106 options = sys.argv[3:]
1.107
1.108 - # Preprocessing options that can be repeated for extra effect.
1.109 + # Basic image properties.
1.110 +
1.111 + width = get_parameter(options, "-W", int, base_width, base_width)
1.112 + number_of_colours = get_parameter(options, "-C", int, 4, 4)
1.113
1.114 - saturate = get_float(options, "-s")
1.115 - desaturate = get_float(options, "-d")
1.116 - darken = get_float(options, "-D")
1.117 - brighten = get_float(options, "-B")
1.118 + # Preprocessing options that employ parameters.
1.119 +
1.120 + saturate = get_parameter(options, "-s", float, 1.0, 0.0)
1.121 + desaturate = get_parameter(options, "-d", float, 1.0, 0.0)
1.122 + darken = get_parameter(options, "-D", float, 1.0, 0.0)
1.123 + brighten = get_parameter(options, "-B", float, 1.0, 0.0)
1.124
1.125 # General output options.
1.126
1.127 @@ -428,19 +425,30 @@
1.128 if make_image or preview:
1.129 exif = EXIF.process_file(open(input_filename))
1.130 im = PIL.Image.open(input_filename).convert("RGB")
1.131 - im = rotate_and_scale(exif, im, width, height, rotate)
1.132 + im = rotate_and_scale(exif, im, base_width, height, rotate)
1.133 +
1.134 + # Scale images to the appropriate width.
1.135 +
1.136 + if width != base_width:
1.137 + im = im.resize((width, height))
1.138
1.139 process_image(im, saturate, desaturate, darken, brighten)
1.140
1.141 # Generate a preview if requested.
1.142
1.143 if preview:
1.144 - preview_image(im, half_resolution_preview).save(preview_filename)
1.145 + imp = im.copy()
1.146 + if half_resolution_preview:
1.147 + imp = imp.resize((width / 2, height))
1.148 + convert_image(imp, 8)
1.149 + if half_resolution_preview:
1.150 + imp = imp.resize((width, height))
1.151 + imp.save(preview_filename)
1.152
1.153 # Generate an output image if requested.
1.154
1.155 if make_image:
1.156 - convert_image(im)
1.157 + convert_image(im, number_of_colours)
1.158 im.save(output_filename)
1.159
1.160 # Verify the output image (which may be loaded) if requested.
1.161 @@ -449,7 +457,7 @@
1.162 if no_normal_output:
1.163 im = PIL.Image.open(output_filename).convert("RGB")
1.164
1.165 - result = count_colours(im, 4)
1.166 + result = count_colours(im, number_of_colours)
1.167 if result is not None:
1.168 y, colours = result
1.169 print "Image %s: row %d has the following colours: %s" % (output_filename, y, "; ".join([repr(c) for c in colours]))