1 unpackmetatile.pl
Oliver Kennedy edited this page 2021-04-13 11:52:43 -04:00
#!/usr/bin/perl -w

use strict;

my $noop;

if( @ARGV && $ARGV[0] eq "-n" ) {
    $noop= 1;
    shift @ARGV;
}

my $transpose;

if( @ARGV && $ARGV[0] eq "-t" ) {
    $transpose= 1;
    shift @ARGV;
}

if( @ARGV != 1 || $ARGV[0] =~ /^--?h(?:elp)?$/i ) {
    print <<EOF;
Usage: unpackmetatile.pl [ -t ] <metatile file>
Extracts all tiles from an OSM metatile.  -t swaps x and y coordinates in the
file names of the resulting image, allowing easy use of ImageMagick montage to
create a composite tile.
EOF
    exit;
}


my ($data, $metamul);

die "Could not open $ARGV[0] for reading: $!\n"
    unless open( IN, "<$ARGV[0]" );

{
    local $/= undef;
    $data= <IN>;
}
close IN;

my ($magic, $ntiles, $x0, $y0, $zoom)= unpack("a4L4", $data);
print STDERR "Warning: Magic mismatch:  " . join(" ", map sprintf("%02X", ord($_)), split //, $magic) . " instead of 4D 45 54 41\n"
    unless $magic eq "META";
$metamul= int(sqrt($ntiles));
print STDERR "Warning: Tile count $ntiles is not a square!\n"
    unless $ntiles == $metamul*$metamul;

# get offset / size table
my @table= unpack("x20 L".$ntiles*2, $data);

my $coorddigits= int($zoom / 3.321928094887 + 1);  # that's ceil(log10(2^zoom))
my $namefmt= "%02d-%0${coorddigits}d-%0${coorddigits}d.png";

tileloop:
for my $dx (0 .. $metamul-1) {
    for my $dy (0 .. $metamul-1) {
        my ($tile)= unpack("x$table[0] a$table[1]", $data);
        my $tilename= $transpose ?
                sprintf( $namefmt, $zoom, $y0 + $dy, $x0 + $dx ) :
                sprintf( $namefmt, $zoom, $x0 + $dx, $y0 + $dy );
        open OUT, ">$tilename" or die "Cannot create output file $tilename!";
        print OUT $tile;
        close OUT;
        splice @table, 0, 2;
        last tileloop unless @table > 1;
    }
}