Thursday, January 19, 2012

flatten3.py

I recently updated flatten.py to strip out pngcrush and use argparse:

#!/usr/bin/env python2 from sys import argv, stderr, exit from subprocess import Popen from argparse import ArgumentParser, ArgumentError from copy import copy from os import remove from os import close as os_close from re import compile as re_compile from os.path import join, isfile, exists from tempfile import mkstemp filext = re_compile('^(.+)\.(.+)$') filext_png = re_compile('\.png$') img_type = ['Bilevel', 'Grayscale', 'GrayscaleMatte', 'Palette', 'PaletteMatte', 'TrueColor', 'TrueColorMatte', 'ColorSeparate', 'ColorSeparationMatte', 'Optimize'] img_cspace = ['CMY', 'CMYK', 'Gray', 'HSB', 'HSL', 'HWB', 'Lab', 'Log', 'OHTA', 'Rec601Luma', 'Rec601YCbCr', 'Rec709Luma', 'Rec709YCbCr', 'RGB', 'sRGB', 'Transparent', 'XYZ', 'YCbCr', 'YCC', 'YIQ', 'YPbPr', 'YUV'] parser = ArgumentParser(usage = 'Usage: %(prog)s [ options ] input [ output ]') parser.add_argument('-s', '--size', dest = 'size', default = None, help = 'The output size; passed directly to ImageMagick') parser.add_argument('-n', '--no-clobber', dest = 'clobber', default = True, action = 'store_false', help = 'Don\'t overwrite the target file') parser.add_argument('-X', '--lossy-reduction', dest = 'lossy_reduction', default = True, action = 'store_false', help = 'Don\'t allow OptiPNG to perform lossy optimizations') parser.add_argument('-f', '--filter', dest = 'filter', default = 'Catrom', help = 'The filter to resize with if necessary') parser.add_argument('-b', '--background', dest = 'background', default = 'white', help = 'The background when flattening') parser.add_argument('-F', '--no-flatten', dest = 'flatten', default = True, action = 'store_false', help = 'Don\'t flatten the output') parser.add_argument('-t', '--type', dest = 'type', choices = img_type + img_cspace, default = None, help = 'The type of the output image: analogous to both -type and -colorspace in ImageMagick') parser.add_argument('-d', '--depth', dest = 'depth', choices = (1, 2, 4, 8, 16), type = int, default = None, help = 'The depth of the output image') parser.add_argument('-p', '--pre-color', dest = 'precolor', default = False, action = 'store_true', help = 'Change bit-depth/colorspace prior to scaling if applicable') parser.add_argument('input', help = 'Input file') parser.add_argument('output', nargs = '?', help = 'Destination file; will default to ${input}_small.png') args = parser.parse_args() if isfile(args.input): pngout = False if args.output: output = args.output if filext_png.search(output): pngout = True else: m = filext.search(args.input) if not m is None: output = '%s_small.%s' % (m.group(1), m.group(2)) if m.group(2) == 'png': pngout = True else: output = '%s_small.png' % args.input pngout = True if not args.clobber and exists(output): print >>stderr, 'Output file exists:', output exit(2) # ACTUAL PROCESSING pargs = ['convert', args.input] if args.precolor: if args.flatten: pargs += ['-background', args.background, '-flatten', '+matte'] if not args.size is None: pargs += ['-filter', args.filter, '-resize', args.size] if not args.type is None: if args.type in img_type: pargs += ['-type', args.type] if not args.depth is None: pargs += ['-depth', str(args.depth)] elif args.type in img_cspace: pargs += ['-colorspace', args.type] if not args.depth is None: pargs += ['-depth', str(args.depth)] if not args.precolor: if args.flatten: pargs += ['-background', args.background, '-flatten', '+matte'] if not args.size is None: pargs += ['-filter', args.filter, '-resize', args.size] if pngout: # Run convert pargs.append('png:' + output) try: Popen(pargs).wait() except KeyboardInterrupt: if isfile(output): remove(output) exit(1) # Run optipng try: optipng = ['optipng', '-o9'] if not args.lossy_reduction: optipng.append('-nx') optipng.append(output) Popen(optipng).wait() except KeyboardInterrupt: if isfile(output): remove(output) else: pargs.append(output) Popen(pargs).wait() # END else: print >>stderr, 'No such file:', args.input exit(2)