Revision 10 (by dpavlin, 2007/10/16 09:27:16) added --flip-vertical option to stich.pl
#!/usr/bin/perl -w

# stich.pl
#
# 10/15/07 22:02:18 CEST Dobrica Pavlinusic <dpavlin@rot13.org>

use strict;

use File::Find;
use Data::Dump qw/dump/;
use Imager;
use Getopt::Long;

# Mireo 1, Google 0
my $flip_vertical = 0;

GetOptions(
	'flip-vertical'	=> \$flip_vertical,
);

my $path = shift @ARGV || die "usage: $0 path_to_dump_dir\n";

my ( $range, $usage );

my @files;
my $file_pos;

find( sub {
	return unless -f $_;
	
	if ( $_ =~ m/(\d+)-(\d+)/ ) {
	
		push @files, $_;

		my ( $x, $y ) = ( $1, $2 );

		$range->{min}->{x} = $x if not defined $range->{min}->{x} or $x < $range->{min}->{x};
		$range->{max}->{x} = $x if not defined $range->{max}->{x} or $x > $range->{max}->{x};

		$range->{min}->{y} = $y if not defined $range->{min}->{y} or $y < $range->{min}->{y};
		$range->{max}->{y} = $y if not defined $range->{max}->{y} or $y > $range->{max}->{y};

		$usage->{x}->{$x}++;
		$usage->{y}->{$y}++;

		$file_pos->{$_} = { x => $x, y => $y };

		warn "## $_\n";

	} else {

		warn "SKIPPED: $_\n";
	}



}, $path );

print "range = ",dump( $range ), "\n";
print "usage = ",dump( $usage ). "\n";

my $step_size;

foreach my $axis ( 'x', 'y' ) {

	my $last = $range->{min}->{$axis};

	foreach my $v ( sort keys %{$usage->{$axis}} ) {

		next if $v == $last;

		$step_size->{$axis}->{ $v - $last }++;
		$last = $v;

	}
	undef $last;
}

print "step_size = ",dump( $step_size ),"\n";

my $step = {
	x => ( sort { $step_size->{x}->{$b} <=> $step_size->{x}->{$a} } keys %{ $step_size->{x} } )[0],
	y => ( sort { $step_size->{y}->{$b} <=> $step_size->{y}->{$a} } keys %{ $step_size->{y} } )[0],
};

print "selected step = ",dump( $step ),"\n";


my $img = Imager->new();
$img->read( file => $path . '/' . $files[0] ) or die $img->errstr();
my $tile_size = {
	x => $img->getwidth,
	y => $img->getheight,
};

print "tile_size = ",dump( $tile_size ),"\n";

my $x_tiles = ( $range->{max}->{x} - $range->{min}->{x} ) / $step->{x};
my $y_tiles = ( $range->{max}->{y} - $range->{min}->{y} ) / $step->{y};

my $x_size = $x_tiles * $tile_size->{x};
my $y_size = $y_tiles * $tile_size->{y};

print "final map size: $x_size x $y_size from $x_tiles x $y_tiles tiles\n";

my $map = Imager->new( xsize => $x_size, ysize => $y_size ) or $img->errstr();

foreach my $tile_file ( @files ) {
	$img->read( file => "$path/$tile_file" ) or die $img->errstr();

	# this is specific to globe position, I guess ... this is europe
	my $x = ( $file_pos->{$tile_file}->{x} - $range->{min}->{x} ) / $step->{x};
	my $y;
	if ( $flip_vertical ) {
		$y = ( $range->{max}->{y} - $file_pos->{$tile_file}->{y} ) / $step->{y};
	} else {
		$y = ( $file_pos->{$tile_file}->{y} - $range->{min}->{y} ) / $step->{y};
	}

	printf("%3dx%-3d %s\n", $x, $y, $tile_file);

	$map->paste(
		src  => $img,
		left => $x * $tile_size->{x},
		top  => $y * $tile_size->{y},
	);
}

$path =~ s/\W+/_/g;
$path =~ s/^_+//;
$path =~ s/_+$//;

$map->write( file => "$path.png" ) or die $img->errstr();