PaletteOptimiser

Changeset

106:a879c7d1d28e
2015-10-11 Paul Boddie raw files shortlog changelog graph Combined the preview and conversion functions, added configuration of the number of chosen colours and the output image width. Fixed option descriptions. simpleimage-shedskin
optimiser.py (file) optimiserlib.py (file)
     1.1 --- a/optimiser.py	Sun Oct 11 00:31:34 2015 +0200
     1.2 +++ b/optimiser.py	Sun Oct 11 15:34:12 2015 +0200
     1.3 @@ -72,15 +72,23 @@
     1.4  
     1.5      return im.resize((width, height))
     1.6  
     1.7 -def get_float(options, flag):
     1.8 +def get_parameter(options, flag, conversion, default, missing):
     1.9 +
    1.10 +    """
    1.11 +    From 'options', return any parameter following the given 'flag', applying
    1.12 +    the 'conversion' which has the given 'default' if no valid parameter is
    1.13 +    found, or returning the given 'missing' value if the flag does not appear at
    1.14 +    all.
    1.15 +    """
    1.16 +
    1.17      try:
    1.18          i = options.index(flag)
    1.19          try:
    1.20 -            return float(options[i+1])
    1.21 +            return conversion(options[i+1])
    1.22          except (IndexError, ValueError):
    1.23 -            return 1.0
    1.24 +            return default
    1.25      except ValueError:
    1.26 -        return 0.0
    1.27 +        return missing
    1.28  
    1.29  # Main program.
    1.30  
    1.31 @@ -100,10 +108,13 @@
    1.32  
    1.33  Options are...
    1.34  
    1.35 --s - Saturate the input image (can be followed by a float, default 1.0)
    1.36 --d - Desaturate the input image (can be followed by a float, default 1.0)
    1.37 --D - Darken the input image (can be followed by a float, default 1.0)
    1.38 --B - Brighten the input image (can be followed by a float, default 1.0)
    1.39 +-W - Indicate the output width (default is 320)
    1.40 +-C - Number of colours per scanline (default is 4)
    1.41 +
    1.42 +-s - Saturate the input image (optional float, 1.0 if unspecified)
    1.43 +-d - Desaturate the input image (optional float, 1.0 if unspecified)
    1.44 +-D - Darken the input image (optional float, 1.0 if unspecified)
    1.45 +-B - Brighten the input image (optional float, 1.0 if unspecified)
    1.46  
    1.47  -r - Rotate the input image clockwise
    1.48  -p - Generate a separate preview image
    1.49 @@ -113,7 +124,7 @@
    1.50  """ % split(sys.argv[0])[1]
    1.51          sys.exit(1)
    1.52  
    1.53 -    width = 320
    1.54 +    base_width = 320
    1.55      height = 256
    1.56  
    1.57      input_filename, output_filename = sys.argv[1:3]
    1.58 @@ -122,12 +133,17 @@
    1.59  
    1.60      options = sys.argv[3:]
    1.61  
    1.62 -    # Preprocessing options that can be repeated for extra effect.
    1.63 +    # Basic image properties.
    1.64 +
    1.65 +    width = get_parameter(options, "-W", int, base_width, base_width)
    1.66 +    number_of_colours = get_parameter(options, "-C", int, 4, 4)
    1.67  
    1.68 -    saturate = get_float(options, "-s")
    1.69 -    desaturate = get_float(options, "-d")
    1.70 -    darken = get_float(options, "-D")
    1.71 -    brighten = get_float(options, "-B")
    1.72 +    # Preprocessing options that employ parameters.
    1.73 +
    1.74 +    saturate = get_parameter(options, "-s", float, 1.0, 0.0)
    1.75 +    desaturate = get_parameter(options, "-d", float, 1.0, 0.0)
    1.76 +    darken = get_parameter(options, "-D", float, 1.0, 0.0)
    1.77 +    brighten = get_parameter(options, "-B", float, 1.0, 0.0)
    1.78  
    1.79      # General output options.
    1.80  
    1.81 @@ -143,7 +159,12 @@
    1.82      if make_image or preview:
    1.83          exif = EXIF.process_file(open(input_filename))
    1.84          im = PIL.Image.open(input_filename).convert("RGB")
    1.85 -        im = rotate_and_scale(exif, im, width, height, rotate)
    1.86 +        im = rotate_and_scale(exif, im, base_width, height, rotate)
    1.87 +
    1.88 +        # Scale images to the appropriate width.
    1.89 +
    1.90 +        if width != base_width:
    1.91 +            im = im.resize((width, height))
    1.92  
    1.93          sim = SimpleImage(list(im.getdata()), im.size)
    1.94          process_image(sim, saturate, desaturate, darken, brighten)
    1.95 @@ -153,16 +174,20 @@
    1.96  
    1.97      if preview:
    1.98          imp = im.copy()
    1.99 -        sim = SimpleImage(list(im.getdata()), im.size)
   1.100 -        simp = preview_image(sim, half_resolution_preview)
   1.101 -        imp.putdata(simp.getdata())
   1.102 +        if half_resolution_preview:
   1.103 +            imp = imp.resize((width / 2, height))
   1.104 +        sim = SimpleImage(list(imp.getdata()), imp.size)
   1.105 +        convert_image(sim, 8)
   1.106 +        imp.putdata(sim.getdata())
   1.107 +        if half_resolution_preview:
   1.108 +            imp = imp.resize((width, height))
   1.109          imp.save(preview_filename)
   1.110  
   1.111      # Generate an output image if requested.
   1.112  
   1.113      if make_image:
   1.114          sim = SimpleImage(list(im.getdata()), im.size)
   1.115 -        convert_image(sim)
   1.116 +        convert_image(sim, number_of_colours)
   1.117          im.putdata(sim.getdata())
   1.118          im.save(output_filename)
   1.119  
   1.120 @@ -173,7 +198,7 @@
   1.121              im = PIL.Image.open(output_filename).convert("RGB")
   1.122  
   1.123          im = SimpleImage(list(im.getdata()), im.size)
   1.124 -        result = count_colours(im, 4)
   1.125 +        result = count_colours(im, number_of_colours)
   1.126          if result is not None:
   1.127              y, colours = result
   1.128              print "Image %s: row %d has the following colours: %s" % (output_filename, y, "; ".join([repr(c) for c in colours]))
     2.1 --- a/optimiserlib.py	Sun Oct 11 00:31:34 2015 +0200
     2.2 +++ b/optimiserlib.py	Sun Oct 11 15:34:12 2015 +0200
     2.3 @@ -249,28 +249,7 @@
     2.4                      rgb = amplify_rgb(rgb, brighten and 0.5 / brighten or 2.0 * darken)
     2.5                  im.putpixel((x, y), rgb)
     2.6  
     2.7 -def preview_image(im, half_resolution_preview=False):
     2.8 -
     2.9 -    "Return a preview copy of image 'im'."
    2.10 -
    2.11 -    width, height = im.size
    2.12 -    imp = im.copy()
    2.13 -    if half_resolution_preview:
    2.14 -        step = 2
    2.15 -    else:
    2.16 -        step = 1
    2.17 -
    2.18 -    for y in range(0, height):
    2.19 -        for x in range(0, width, step):
    2.20 -            rgb = im.getpixel((x, y))
    2.21 -            value = get_value(rgb)
    2.22 -            imp.putpixel((x, y), value)
    2.23 -            if half_resolution_preview:
    2.24 -                imp.putpixel((x+1, y), value)
    2.25 -
    2.26 -    return imp
    2.27 -
    2.28 -def convert_image(im):
    2.29 +def convert_image(im, colours):
    2.30  
    2.31      "Convert image 'im' to an appropriate output representation."
    2.32  
    2.33 @@ -279,7 +258,7 @@
    2.34      for y in range(0, height):
    2.35          c = get_colours(im, y)
    2.36  
    2.37 -        for l in get_combinations(c, 4):
    2.38 +        for l in get_combinations(c, colours):
    2.39              most = [value for f, value in l]
    2.40              for x in range(0, width):
    2.41                  rgb = im.getpixel((x, y))
    2.42 @@ -289,7 +268,7 @@
    2.43              else:
    2.44                  break # use this combination
    2.45          else:
    2.46 -            most = [value for f, value in c[:4]] # use the first four
    2.47 +            most = [value for f, value in c[:colours]] # use the first colours
    2.48  
    2.49          for x in range(0, width):
    2.50              rgb = im.getpixel((x, y))
    2.51 @@ -359,7 +338,6 @@
    2.52      count_colours(im, 4)
    2.53  
    2.54      process_image(im, 1.0, 0.0, 1.0, 0.0)
    2.55 -    preview_image(im, False)
    2.56 -    convert_image(im)
    2.57 +    convert_image(im, 4)
    2.58  
    2.59  # vim: tabstop=4 expandtab shiftwidth=4