#! /usr/bin/python

# Copyright (C) 2000 Intevation GmbH <intevation@intevation.de>
# Author: Bernhard Herzog <bh@intevation.de>
#
# This program is free software under the LGPL (>=v2)
# Read the file COPYING coming with MapIt! for details.
"""Paste all MapIt! tiles in one directory into one image

Usage: pastetiles dir outputfile

Read all image files in the directory dir and paste them into one giant
image and write it as outputfile. The output file type is determined
from the output filename.

The names of the image files must follow the scheme used by the
mapit-tiles, that is, <x>x<y>.<ext> where <x> and <y> are the indices of
the tile. The indices are expected to follow the same scheme as the ones
in the examples where the y index increases from bottom to top.

NOTE: The result image is held completely in memory, so the script may
require *huge* amounts of memory.
"""

__version__="$Revision: 1.4 $"

import os, sys, re
import PIL.Image


# regex that matches a mapit tile filename. 
rx_image_filename = re.compile(r"(?P<x>[0-9]+)x(?P<y>[0-9]+)\.")

def find_image_files(dir):
    """ Find files matching rx_image_filename.

    Find all files in dir that match the regex and return a list of tuples
    of the form (x, y, filename). x and y are the indices of the tile and
    filename is the absolute filename (well, actually 
    """
    filenames = os.listdir(dir)
    image_files = []
    xs = []
    ys = []
    for filename in filenames:
        match = rx_image_filename.match(filename)
        if match:
            x = int(match.group("x"))
            y = int(match.group("y"))
            image_files.append((x, y, os.path.join(dir, filename)))
            xs.append(x)
            ys.append(y)
    return xs, ys, image_files


def paste_tiles(dir):
    """Read all images in dir and return a big result image with all of them."""
    xs, ys, imagefiles = find_image_files(dir)
    if not imagefiles:
        sys.stderr.write("No image files in %s\n" % dir)
        return None

    minx = min(xs); maxx = max(xs)
    miny = min(ys); maxy = max(ys)
    
    tile = PIL.Image.open(imagefiles[0][-1])
    tile_width, tile_height = tile.size
    total_width = (maxx - minx + 1) * tile_width
    total_height = (maxy - miny + 1) * tile_height
    result = PIL.Image.new("RGB", (total_width, total_height), 0xFFFFFFFF)
    for x, y, file in imagefiles:
#        print 'processing', file
        tile = PIL.Image.open(file)
        x = (x - minx) * tile_width
        y = (maxy - y) * tile_height
        result.paste(tile, (x, y))
    return result

def main():
    """Parse command line parameters, run paste_tiles and save result image."""
    if len(sys.argv) != 3:
        print __doc__
        sys.exit(1)
    dir = sys.argv[1]
    output = sys.argv[2]
    image = paste_tiles(dir)
    if image:
#        print 'saving', output
        image.save(output)


if __name__ == '__main__':
    main()
