PaletteOptimiser

Change of main.py

71:ba632fd74cbb
main.py shedskin
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/main.py	Fri Oct 09 23:48:21 2015 +0200
     1.3 @@ -0,0 +1,174 @@
     1.4 +#!/usr/bin/env python
     1.5 +
     1.6 +"""
     1.7 +Convert and optimise images for display in an Acorn Electron MODE 1 variant
     1.8 +with four colours per line but eight colours available for selection on each
     1.9 +line.
    1.10 +
    1.11 +Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
    1.12 +
    1.13 +This program is free software; you can redistribute it and/or modify it under
    1.14 +the terms of the GNU General Public License as published by the Free Software
    1.15 +Foundation; either version 3 of the License, or (at your option) any later
    1.16 +version.
    1.17 +
    1.18 +This program is distributed in the hope that it will be useful, but WITHOUT ANY
    1.19 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
    1.20 +PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    1.21 +
    1.22 +You should have received a copy of the GNU General Public License along
    1.23 +with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.24 +"""
    1.25 +
    1.26 +from optimiser import *
    1.27 +from os.path import split, splitext
    1.28 +import EXIF
    1.29 +import PIL.Image
    1.30 +import sys
    1.31 +
    1.32 +def rotate_and_scale(exif, im, width, height, rotate):
    1.33 +
    1.34 +    """
    1.35 +    Using the given 'exif' information, rotate and scale image 'im' given the
    1.36 +    indicated 'width' and 'height' constraints and any explicit 'rotate'
    1.37 +    indication. The returned image will be within the given 'width' and
    1.38 +    'height', filling either or both, and preserve its original aspect ratio.
    1.39 +    """
    1.40 +
    1.41 +    if rotate or exif and exif["Image Orientation"].values == [6L]:
    1.42 +        im = im.rotate(270)
    1.43 +
    1.44 +    w, h = im.size
    1.45 +    if w > h:
    1.46 +        height = (width * h) / w
    1.47 +    else:
    1.48 +        width = (height * w) / h
    1.49 +
    1.50 +    return im.resize((width, height))
    1.51 +
    1.52 +def test():
    1.53 +
    1.54 +    "Generate slices of the colour cube."
    1.55 +
    1.56 +    size = 64
    1.57 +    for r in (0, 63, 127, 191, 255):
    1.58 +        pim = PIL.Image.new("RGB", (size, size))
    1.59 +        im = SimpleImage(list(pim.getdata()), pim.size)
    1.60 +        test_slice(im, size, r)
    1.61 +        pim.putdata(im.getdata())
    1.62 +        pim.save("rgb%d.png" % r)
    1.63 +
    1.64 +def test_flat(rgb):
    1.65 +
    1.66 +    "Generate a flat image for the colour 'rgb'."
    1.67 +
    1.68 +    size = 64
    1.69 +    pim = PIL.Image.new("RGB", (size, size))
    1.70 +    im = SimpleImage(list(pim.getdata()), pim.size)
    1.71 +    test_flat_slice(im, size, rgb)
    1.72 +    pim.putdata(im.getdata())
    1.73 +    pim.save("rgb%02d%02d%02d.png" % rgb)
    1.74 +
    1.75 +def get_float(options, flag):
    1.76 +    try:
    1.77 +        i = options.index(flag)
    1.78 +        if i+1 < len(options) and options[i+1].isdigit():
    1.79 +            return float(options[i+1])
    1.80 +        else:
    1.81 +            return 1.0
    1.82 +    except ValueError:
    1.83 +        return 0.0
    1.84 +
    1.85 +# Main program.
    1.86 +
    1.87 +if __name__ == "__main__":
    1.88 +
    1.89 +    # Test options.
    1.90 +
    1.91 +    if "--test" in sys.argv:
    1.92 +        test()
    1.93 +        sys.exit(0)
    1.94 +    elif "--test-flat" in sys.argv:
    1.95 +        test_flat((120, 40, 60))
    1.96 +        sys.exit(0)
    1.97 +    elif "--help" in sys.argv:
    1.98 +        print >>sys.stderr, """\
    1.99 +Usage: %s <input filename> <output filename> [ <options> ]
   1.100 +
   1.101 +Options are...
   1.102 +
   1.103 +-s - Saturate the input image (can be followed by a float, default 1.0)
   1.104 +-d - Desaturate the input image (can be followed by a float, default 1.0)
   1.105 +-D - Darken the input image (can be followed by a float, default 1.0)
   1.106 +-B - Brighten the input image (can be followed by a float, default 1.0)
   1.107 +
   1.108 +-r - Rotate the input image clockwise
   1.109 +-p - Generate a separate preview image
   1.110 +-h - Make the preview image with half horizontal resolution (MODE 2)
   1.111 +-v - Verify the output image (loaded if -n is given)
   1.112 +-n - Generate no output image
   1.113 +""" % split(sys.argv[0])[1]
   1.114 +        sys.exit(1)
   1.115 +
   1.116 +    width = 320
   1.117 +    height = 256
   1.118 +
   1.119 +    input_filename, output_filename = sys.argv[1:3]
   1.120 +    basename, ext = splitext(output_filename)
   1.121 +    preview_filename = "".join([basename + "_preview", ext])
   1.122 +
   1.123 +    options = sys.argv[3:]
   1.124 +
   1.125 +    # Preprocessing options that can be repeated for extra effect.
   1.126 +
   1.127 +    saturate = get_float(options, "-s")
   1.128 +    desaturate = get_float(options, "-d")
   1.129 +    darken = get_float(options, "-D")
   1.130 +    brighten = get_float(options, "-B")
   1.131 +
   1.132 +    # General output options.
   1.133 +
   1.134 +    rotate = "-r" in options
   1.135 +    preview = "-p" in options
   1.136 +    half_resolution_preview = "-h" in options
   1.137 +    verify = "-v" in options
   1.138 +    no_normal_output = "-n" in options
   1.139 +    make_image = not no_normal_output
   1.140 +
   1.141 +    # Load the input image if requested.
   1.142 +
   1.143 +    if make_image or preview:
   1.144 +        exif = EXIF.process_file(open(input_filename))
   1.145 +        pim = PIL.Image.open(input_filename).convert("RGB")
   1.146 +        pim = rotate_and_scale(exif, pim, width, height, rotate)
   1.147 +        im = SimpleImage(list(pim.getdata()), pim.size)
   1.148 +        process_image(im, saturate, desaturate, darken, brighten)
   1.149 +
   1.150 +    # Generate a preview if requested.
   1.151 +
   1.152 +    if preview:
   1.153 +        imp = preview_image(im, half_resolution_preview)
   1.154 +        pimp = pim.copy()
   1.155 +        pimp.putdata(imp.getdata())
   1.156 +        pimp.save(preview_filename)
   1.157 +
   1.158 +    # Generate an output image if requested.
   1.159 +
   1.160 +    if make_image:
   1.161 +        convert_image(im)
   1.162 +        pim.putdata(im.getdata())
   1.163 +        pim.save(output_filename)
   1.164 +
   1.165 +    # Verify the output image (which may be loaded) if requested.
   1.166 +
   1.167 +    if verify:
   1.168 +        if no_normal_output:
   1.169 +            pim = PIL.Image.open(output_filename).convert("RGB")
   1.170 +            im = SimpleImage(list(pim.getdata()), pim.size)
   1.171 +
   1.172 +        result = count_colours(im, 4)
   1.173 +        if result is not None:
   1.174 +            y, colours = result
   1.175 +            print "Image %s: row %d has the following colours: %s" % (output_filename, y, "; ".join([repr(c) for c in colours]))
   1.176 +
   1.177 +# vim: tabstop=4 expandtab shiftwidth=4