PaletteOptimiser

Change of optimiser.py

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