Skip to content

Instantly share code, notes, and snippets.

@eikes eikes/
Created Jun 5, 2010

What would you like to do?
# configure here:
# first top left (north west)
my $startlon = 13.40991;
my $startlat = 52.48905;
# then bottom right (south east)
my $endlon = 13.42209;
my $endlat = 52.47982;
#zoom level:
my $zoom = 16;
# end of configuration
use strict;
use LWP;
use GD;
use Math::Trig;
sub getTileNumber {
my ($lat,$lon,$zoom) = @_;
my $xtile = int( ($lon+180)/360 *2**$zoom ) ;
my $ytile = int( (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat)))/pi)/2 *2**$zoom ) ;
return ($xtile, $ytile);
(my $xstart, my $ystart) = getTileNumber($startlat, $startlon, $zoom);
(my $xend, my $yend) = getTileNumber($endlat, $endlon, $zoom);
my $tilesize = 256;
# calc image size
my $xsize = ($xend-$xstart+1) * $tilesize;
my $ysize = ($yend-$ystart+1) * $tilesize;
my $img = GD::Image->new($xsize, $ysize, 1);
my $white = $img->colorAllocate(248,248,248);
my $ua = LWP::UserAgent->new();
for (my $x=$xstart;$x<=$xend;$x++) {
for (my $y=$ystart;$y<=$yend;$y++) {
my $url = sprintf("", $zoom, $x, $y);
print STDERR "$url... ";
my $resp = $ua->get($url);
print STDERR $resp->status_line;
print STDERR "\n";
next unless $resp->is_success;
my $tile = GD::Image->new($resp->content);
next if ($tile->width == 1);
$img->copy($tile, ($x-$xstart)*256,($y-$ystart)*256,0,0,256,256);
binmode STDOUT;
print $img->png();

This comment has been minimized.

Copy link

harry-wood commented Apr 18, 2011

I take it this is a modified version of the perl script generated by "BigMap" ( )

I also modified the BigMap script. Take a look at linked from here: This includes various tricks to make the tile scraping script more friendly to the OpenStreetMap server (important when re-running regularly)

  • Mirrors to local tile files, only downloading when modified ($ua->mirror line)
  • Skip ocean tiles (a bit hardcoded although it also detects ocean tiles to build a skip list)
  • Sleeps every 15 tiles to give the server a break.

Also various code tidying to make it more configurable, although I haven't done the lat/lon to tile number conversion you've done here. That could be handy


This comment has been minimized.

Copy link

tengel commented Sep 21, 2011

The resulting png file is pretty large. I tried to reduce the size using:
$img->trueColorToPalette(0, 255);
print $img->png(9);
which works fine, but I think the original files are still smaller then the files created by this script. Any ideas how to get smaller files without corrupting colours?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.