Thanks to Pedro’s post, I was finally able to create a zoomable image viewer using GDAL and Leaflet.
First, you must make sure that your image adhere’s to the tile size chart:
Zoom Level Pixel size 0 256 1 512 2 1024 3 2048 4 4096 5 8192 6 16384 7 32768 8 65536
Then make sure that the larger side of your image (width or height) is sized to the exact pixel size. To do so, run the following command:
gdal_translate -of JPEG -outsize 32768 3407 coast3.jpg coast3-resized.jpg
In this example, zoom level 7 was chosen, so the pixel size is 32768. You will need to calculate what the pixel height is based on the ratio of the image dimensions. Since the original image is 40400 x 4200, the adjusted dimensions are 32768 x 3407.
When you run the above command, you should get a response like so:
Input file size is 40400, 4200 0...10...20...30...40...50...60...70...80...90...100 - done.
Now it is time to tile the image and create the image viewer. We will use the command gdal2tile.py to accomplish this.
gdal2tiles.py -p raster -z 0-7 -w all coast3-resized.jpg coast3
This creates a “coast3” folder with all the tiles inside. While gdal creates some default web viewers, I have opted to create my own using leaflet. Here is the code for the viewer:
<html> <head> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" /> <style> html, body, #map { width:100%; height:100%; margin:0; padding:0; } </style> </head> <body> <div id="map"></div> <script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script> <script> var mapMinZoom = 0; var mapMaxZoom = 7; var map = L.map('map', { maxZoom: mapMaxZoom, minZoom: mapMinZoom, crs: L.CRS.Simple }).setView([-180, 90], 0); var mapBounds = new L.LatLngBounds( map.unproject([0, 32768],mapMaxZoom), map.unproject([32768, 30015],mapMaxZoom)); map.fitBounds(mapBounds); L.tileLayer('{z}/{x}/{y}.png', { minZoom: 0, maxZoom: 7, attribution: 'UCLA/NiigataUniversity', tms: true, noWrap: true }).addTo(map); </script> </body> </html>
There are some numbers that need to be adjusted. The mapMinZoom and mapMaxZoom need to be adjusted depending on what parameters were chosen to tile the image. Furthermore, the mapBounds numbers need to be calculated. To do so, open the folder with the tiles (coast3 in this example), and examine the tilemapresource.xml file that was automatically generated by gdal. It should look like this:
<?xml version="1.0" encoding="utf-8"?> <TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0"> <Title>coast3-resized.jpg</Title> <Abstract></Abstract> <SRS></SRS> <BoundingBox minx="0.00000000000000" miny="-3407.00000000000000" maxx="32768.00000000000000" maxy="0.00000000000000"/> <Origin x="0.00000000000000" y="-3407.00000000000000"/> <TileFormat width="256" height="256" mime-type="image/png" extension="png"/> <TileSets profile="raster"> <TileSet href="0" units-per-pixel="128.00000000000000" order="0"/> <TileSet href="1" units-per-pixel="64.00000000000000" order="1"/> <TileSet href="2" units-per-pixel="32.00000000000000" order="2"/> <TileSet href="3" units-per-pixel="16.00000000000000" order="3"/> <TileSet href="4" units-per-pixel="8.00000000000000" order="4"/> <TileSet href="5" units-per-pixel="4.00000000000000" order="5"/> <TileSet href="6" units-per-pixel="2.00000000000000" order="6"/> <TileSet href="7" units-per-pixel="1.00000000000000" order="7"/> </TileSets> </TileMap>
Observe the numbers in the BoundingBox parameter. These are needed in order to calculate the mapBounds parameters in leaflet. Here is the rough formula:
map.unproject([minx,maxx],mapMaxZoom), map.unproject([maxx,maxx+miny],mapMaxZoom)
And here is the results:
hi, i was in the same case as you . So nice explanation here ! it helped me out to figure what was the issue .
However , using outsize will resample your image … What if you do not want to have any deformation (resample) , just fill with alpha transparent pixels your image to the right size ?
eg :
outsizing from 2047X255 to 2048X256 wont be noticeable , but if you outsize from 2049X255 to 4096X256 , you might see a change ( i’m talking more about 500.000X40.000 images here =) )
Did you had the same issue ?
This wonderful recipe no longer works on modern leaflet (>0.6), sad because it is one I still use today, but I have to use old leaflet to do it.