Source

panslice / panslice / panslice.py

Full commit
import sys
import optparse
import math
import os.path

import Image

def slice_image(input_filename, slice_width=None, x_center=False,
                y_center=False, ratio=(4.0, 3.0), output_path='.'):
    im = Image.open(input_filename)

    if not slice_width:
        slice_width = int((im.size[1] / ratio[1]) * ratio[0])

    if y_center:
        d, r = divmod(im.size[0], slice_width)
        x_correction = float(r) / float(d)
        y_offset = int(round(((((slice_width + x_correction) / ratio[0]) * 
                       ratio[1] - im.size[1]) / 2.0)))
        slice_width += int(math.ceil(x_correction))
    else:
        y_offset = 0

    if x_center and not y_center:
        x_offset = (slice_width - im.size[0] % slice_width) / 2
    else:
        x_offset = 0

    for i, x in enumerate(range(-x_offset, im.size[0], slice_width)):
        tile = im.crop((x, -y_offset, x + slice_width, im.size[1]+y_offset))
        tilefilename = os.path.join(output_path, 
            '%s_tile_%03d.jpg' % (input_filename, (i+1)))
        if os.path.exists(tilefilename):
            raise RuntimeError('File %s already exists.' % (tilefilename,))
        tile.save(tilefilename, quality=95)
        sys.stdout.write('.')
        sys.stdout.flush()
    print ' Done.'


def cli():
    parser = optparse.OptionParser()
    parser.add_option('--xcenter', action='store_true', dest='x_center', 
                      default=False, help='x center')
    parser.add_option('--ycenter', action='store_true', dest='y_center', 
                      default=False, 
                      help='y center (takes precedence over x center)')
    parser.add_option('--ratio', action='store', dest='ratio', default='4x3', 
                      help='target ratio for a tile (default: %default)')
    parser.add_option('--output', action='store', dest='output_path',
                      default='.', help='Output path (default: %default)')
    opts, args = parser.parse_args()

    try:
        ratio = [float(x) for x in opts.ratio.split('x')]
    except ValueError:
        sys.exit('Error: Invalid ratio format. Cannot convert to float.')
    else:
        if len(ratio) != 2:
            sys.exit('Error: Invalid ratio format. Need exactly two numbers ' \
                'separated by an "x"')

    if not os.path.exists(opts.output_path):
        sys.exit('Error: Path %s does not exist.' % (opts.output_path,))

    if len(args) not in (1, 2):
        sys.exit('Usage: %s [options] <input file> [<slice width>]' 
            % (sys.argv[0],))
    else:
        if len(args) == 2:
            slice_image(args[0], int(args[1]), opts.x_center, opts.y_center,
                        ratio=ratio, output_path=opts.output_path)
        else:
            slice_image(args[0], x_center=opts.x_center, y_center=opts.y_center,
                        ratio=ratio, output_path=opts.output_path)