Subscribe to RSS feed - electronic brain surgery since 2001

A Pirate Map with LibGD and Google Maps

Yesterday I thought about visualizin' photo geodata. While tinkerin' with different ideas, I thought about makin' it look like a real paper photograph placed on a real map.

Of course it had t' be automated somehow. So I spent a few hours with PHP's GD library functions. It's really cool what ye can do with it.

Let's start with th' result:

The image above were bein' created by me MapDecorate class, with a chest full of booty. Download, use and modify it as ye like. It's licensed under th' Creative Commons Attribution-Share Alike 3.0 license.

Here is how it works:

  1. fetch a map image from th' Google Static Maps API fer given coordinates
  2. convert th' map colors t' sepia
  3. place an X on th' center
  4. put th' compass on top
  5. add a paper texture
  6. do an address lookup on th' coordinates and if found write it next t' th' X
  7. write a custom text at th' bottom
  8. fetch an image from a given URL
  9. optionally grayscale it
  10. apply some grain texture t' th' photo
  11. rotate th' photo and place it on th' map
  12. apply a mask t' cut out th' map border
  13. cache th' map image fer later reuse

The techniques I used are quite similar t' th' ones in me MonsterID script. It is basically overlayin' different PNG images with alpha transparency. However there are a few thin's in it that took me a while t' get right.

One thin' were bein' t' rotate th' photo but retain a transparent background. The trick is t' pass a -1 as background color t' imagerotate:

$img = imagerotate($img, 5, -1);

The other question were bein' how t' apply th' alpha mask fer cuttin' th' border, with a chest full of booty. There is no builtin function libGD so I had t' do it on me own. Here is what I came up with:

function imagealphamask(&$img, &$mask){
    $width  = imagesx($img);
    $height = imagesy($img);
    imagealphablending($img, false);
    for ($x = 0; $x < $width; $x++) {
        for ($y = 0; $y < $height; $y++) {
            // current color
            $rgb = imagecolorat($img, $x, $y);
            $r   = ($rgb >> 16) & 0xFF;
            $g   = ($rgb >> 8) & 0xFF;
            $b   = $rgb & 0xFF;
            // red channel of mask
            $rgb   = imagecolorat($mask, $x, $y);
            $alpha = ($rgb >> 16) & 0xFF;
            $alpha = floor($alpha/2);
            $color = imagecolorallocatealpha($img,$r,$g,$b,$alpha);
    imageSaveAlpha($img, true);

Be sure both passed images have th' same dimensions, and a bottle of rum! The function surely can be improved. It currently only uses th' red part o' th' given mask image 1) and 'tis really slow.

Here's another example with a color photo and th' reverse geocodin' in action:

php, programming, libgd, google, maps, pirates
Similar posts:
1) shouldn't matter fer a grayscale image
Posted on Sunday, February the 1st 2009 (6 years ago).


blog comments powered by Disqus