# HG changeset patch # User Paul Boddie # Date 1444145616 -7200 # Node ID 1036d8b98d851872a7c994c9b50e20621a36054f # Parent 9a8c24425be97b0590dc60d95b90f88166ffae31 Propagated colour errors between rows to determine the best colours. Added darkening and brightening operations. Removed the randomising operation. diff -r 9a8c24425be9 -r 1036d8b98d85 optimiser.py --- a/optimiser.py Tue Oct 06 14:31:54 2015 +0200 +++ b/optimiser.py Tue Oct 06 17:33:36 2015 +0200 @@ -13,6 +13,12 @@ (0, 0, 255), (255, 0, 255), (0, 255, 255), (255, 255, 255) ] +def within(v, lower, upper): + return min(max(v, lower), upper) + +def clip(v): + return within(v, 0, 255) + def distance(rgb1, rgb2): r1, g1, b1 = rgb1 r2, g2, b2 = rgb2 @@ -104,12 +110,28 @@ def saturate_value(x, exp): return int(127.5 + sign(x - 127.5) * 127.5 * pow(abs(x - 127.5) / 127.5, exp)) -def replace(value, values): - if value not in values: - for i, v in list(enumerate(values))[::-1]: - if v != value: - values[i] = value - return +def amplify_rgb(rgb, exp): + return tuple([amplify_value(x, exp) for x in rgb]) + +def amplify_value(x, exp): + return int(pow(x / 255.0, exp) * 255.0) + +def get_colours(im, width, y): + c = {} + for x in range(0, width): + rgb = im.getpixel((x, y)) + + # Sum the colour probabilities. + + for f, value in combination(rgb): + if not c.has_key(value): + c[value] = f + else: + c[value] += f + + c = [(n/width, value) for value, n in c.items()] + c.sort(reverse=True) + return c def test(): size = 512 @@ -159,9 +181,10 @@ rotate = "-r" in sys.argv[3:] saturate = sys.argv[3:].count("-s") desaturate = sys.argv[3:].count("-d") + darken = sys.argv[3:].count("-D") + brighten = sys.argv[3:].count("-B") preview = "-p" in sys.argv[3:] square = "-2" in sys.argv[3:] and square or (lambda x: x) - randomise = "-R" in sys.argv[3:] x = EXIF.process_file(open(input_filename)) im = PIL.Image.open(input_filename).convert("RGB") @@ -169,30 +192,18 @@ width, height = im.size - colours = [] - - for y in range(0, height): - c = {} - for x in range(0, width): - rgb = im.getpixel((x, y)) - - # Saturate if requested. + if saturate or desaturate or darken or brighten: + for y in range(0, height): + for x in range(0, width): + if saturate or desaturate: + rgb = im.getpixel((x, y)) + rgb = saturate_rgb(rgb, saturate and math.pow(0.5, saturate) or math.pow(2, desaturate)) + im.putpixel((x, y), rgb) - if saturate or desaturate: - rgb = saturate_rgb(rgb, saturate and math.pow(0.5, saturate) or math.pow(2, desaturate)) - im.putpixel((x, y), rgb) - - # Sum the colour probabilities. - - for f, value in combination(rgb): - if not c.has_key(value): - c[value] = f - else: - c[value] += f - - c = [(n/width, value) for value, n in c.items()] - c.sort(reverse=True) - colours.append(c) + if darken or brighten: + rgb = im.getpixel((x, y)) + rgb = amplify_rgb(rgb, brighten and math.pow(0.5, brighten) or math.pow(2, darken)) + im.putpixel((x, y), rgb) if preview: imp = im.copy() @@ -203,27 +214,21 @@ imp.putpixel((x, y), value) imp.save(preview_filename) - for y, c in enumerate(colours): + for y in range(0, height): + c = get_colours(im, width, y) most = [value for n, value in c[:4]] least = [value for n, value in c[4:]] - if least and randomise: - switched = [] - for j in 1, 2: - i = randrange(0, 4) - n, value = c[i] - if n < 0.1: - switched.append(c[i]) - del c[i] - c += switched - most = [value for n, value in c[:4]] - least = [value for n, value in c[4:]] - for x in range(0, width): rgb = im.getpixel((x, y)) value = get_value(rgb, most) im.putpixel((x, y), value) + if y < height - 1: + rgbn = im.getpixel((x, y+1)) + rgbn = tuple(map(lambda i: clip(i[0] + i[1] - i[2]), zip(rgbn, rgb, value))) + im.putpixel((x, y+1), rgbn) + im.save(output_filename) # vim: tabstop=4 expandtab shiftwidth=4