Creating your own Google Maps tiles in OSX
Have you ever thought of creating your own custom map and displaying it using Google Maps? Well, I did and I want to share the experience. The goal was to be able to use an old map to display a kayak trip I did some time ago. I put together a whole website around that trip, MenorKayak.
Menorca Island
To generate the tiles, I originally used a high resolution image from the Institut Cartogràfic i Geològic de Catalunya. They have a very nice collection of old maps available here that I totally recommend checking it out if you're into this sort of stuff.
Installing GDAL
GDAL is a very cool library for raster geospatial data formats. More info available here. You can download the complete framework from http://www.kyngchaos.com/software:frameworks#gdal_complete.
Add GDAL to your PATH:
echo 'export PATH=/Library/Frameworks/GDAL.framework/Programs:$PATH' >> ~/.bash_profile
Ensure it's working by checking the output of GDAL to your PATH:
gdal-config --version
By the time I did it the version was 1.10.1.
Getting your area template
Now you have to choose the area where you want to overlay your own map. Go to http://www.maptiler.org/photoshop-google-maps-overlay-tiles and follow steps 1 and 2. No need to follow the rests of steps mentioned there.
- Step 1: Pan and zoom the map until you see the exact area you want to overlay.
Step 2: Save the image on your computer.
After this you're gonna need the corner coordinates of the selected area. To find them out, in that very same page, open your Javascript console and execute:
map.getBounds().toString()
Now you have the lat/lng bounds of the current map. In my case:
"((39.61168293107564, 3.6198320749999766), (40.28546166826872, 4.498738324999977))"
With these two pair of coordinates (SW and NE) you can already figure out the four corners:
3.6198320749999766, 40.28546166826872 4.498738324999977, 40.28546166826872 3.6198320749999766, 39.61168293107564 4.498738324999977, 39.61168293107564
In my case the downloaded image looked like:
Bounding box area
Overlaying images
Now you need to use Photoshop or any other similar software to overlay your own map and the downloaded image from the previous step. Open your custom image, add the downloaded Google Map image as a layer and use the opacity controls to adjust them. Once you're done save the result, JPG or PNG depending if you need transparency or not. I used JPG because I didn't need any transparency. If you're using a weather map or similar then go for PNG option.
Generating the tiles
Now that you have your own custom image you're ready to use GDAL to create the map tiles. Tiles are small images of 256x256 used by Google Maps.
Check your custom image:
gdalinfo yourimage.jpg
Output:
Driver: JPEG/JPEG JFIF Files: yourimage.jpg Size is 5604, 5624 Coordinate System is Metadata: EXIF_BitsPerSample=8 8 8 EXIF_ColorSpace=65535 EXIF_Compression=1 EXIF_DateTime=2014:01:09 14:34:21 EXIF_Make=Metis Systems srl EXIF_Model=Metis DRS 2A0 - CCD 14.4K - Firmware : 0001.01 EXIF_Orientation=1 EXIF_PhotometricInterpretation=2 EXIF_PixelXDimension=5604 EXIF_PixelYDimension=5624 EXIF_PlanarConfiguration=1 EXIF_ResolutionUnit=2 EXIF_SamplesPerPixel=3 EXIF_Software=Adobe Photoshop CS3 Macintosh EXIF_XResolution=(300) EXIF_YResolution=(300) Image Structure Metadata: COMPRESSION=JPEG INTERLEAVE=PIXEL SOURCE_COLOR_SPACE=YCbCr Corner Coordinates: Upper Left ( 0.0, 0.0) Lower Left ( 0.0, 5624.0) Upper Right ( 5604.0, 0.0) Lower Right ( 5604.0, 5624.0) Center ( 2802.0, 2812.0) Band 1 Block=5604x1 Type=Byte, ColorInterp=Red Overviews: 2802x2812, 1401x1406, 701x703 Image Structure Metadata: COMPRESSION=JPEG Band 2 Block=5604x1 Type=Byte, ColorInterp=Green Overviews: 2802x2812, 1401x1406, 701x703 Image Structure Metadata: COMPRESSION=JPEG Band 3 Block=5604x1 Type=Byte, ColorInterp=Blue Overviews: 2802x2812, 1401x1406, 701x703 Image Structure Metadata: COMPRESSION=JPEG
Now we need to create a VRT file using the command gdal_translate. Remember to change the coordinates with your own corner coordinates.
gdal_translate -of VRT -a_srs EPSG:4326 -gcp 0 0 3.6198320749999766 40.28546171792043 -gcp 5604 0 4.498738324999977 40.28546171792043 -gcp 0 5624 3.6198320749999766 39.61168298121881 -gcp 5604 5624 4.498738324999977 39.61168298121881 yourimage.jpg output.vrt
Now do the WARP:
gdalwarp -of VRT -t_srs EPSG:4326 output.vrt new_output.vrt
Generate the tiles ready to use with Google Maps:
gdal2tiles.py -p geodetic new_output.vrt
In your directory you'll see a bunch of folders and some auto-generated HTML files. These are the tiles folders and a couple of examples using Google Maps and Open Layers. The Google Maps example might not work properly because the generated code uses an old version of the Google Maps Javascript API. A Google Maps JS example that works:
$(document).ready(function() {
var map;
function initialize() {
var mapMinZoom = 8;
var mapMaxZoom = 13;
var center = new google.maps.LatLng(39.94940191877162, 4.059285199999977);
var myOptions = {
zoom: 10,
center: center,
mapTypeId: google.maps.MapTypeId.SATELLITE,
mapTypeControl: false,
streetViewControl: false
};
map = new google.maps.Map(document.getElementById('small-map'), myOptions);
//Custom tiles overlay
var mapBounds = new google.maps.LatLngBounds(new google.maps.LatLng(39.6116914406, 3.619832075), new google.maps.LatLng(40.2854617179, 4.49872734429));
var imageMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom, ownerDocument) {
var zfactor = Math.pow(2,zoom);
if ((zoom < mapMinZoom) || (zoom > mapMaxZoom)) {
return '/images/none.png';
}
var ymax = 1 << zoom;
var y = ymax - coord.y -1;
var tileBounds = new google.maps.LatLngBounds(
map.getProjection().fromPointToLatLng( new google.maps.Point( ((coord.x)*256) / zfactor, ((coord.y+1)*256)/ zfactor ) ),
map.getProjection().fromPointToLatLng( new google.maps.Point( ((coord.x+1)*256)/ zfactor, ((coord.y)*256 )/ zfactor ) )
);
if (mapBounds.intersects(tileBounds)) {
return '/path_to_tiles/'+zoom+"/"+coord.x+"/"+y+".png";
} else {
return '/images/none.png';
}
},
tileSize: new google.maps.Size(256, 256),
maxZoom: mapMinZoom,
minZoom: mapMaxZoom,
opacity:1
});
map.overlayMapTypes.push(imageMapType);
}
google.maps.event.addDomListener(window, 'load', initialize);
});
Remember to set the path to your tiles folder or might not work properly.
And that's all! Now you should be able to generate your own custom map/layers and create some impressive stuff with Google Maps or another Map Server ;)
SOURCES:
- http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/the-google-maps-api-and-custom-overlays/
- http://www.maptiler.org/photoshop-google-maps-overlay-tiles/
- http://gis.stackexchange.com/questions/27321/understanding-the-map-tile-creation-properties
- http://www.gdal.org/index.html
- http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries
- https://developers.google.com/kml/articles/raster
- See All
- Next