We are producing tiles from a geotiff using gdal2tiles.py (GDAL 2.1.0dev) to feed a web-system we are developing. We use openlayers 3 (v3.18.2) on the web-system. The gdal2tiles.py by @Klokan Technologies Gmb works great. and we can nicely view the tiles using the automatically generated webviewer: openlayers.html, leaflet.html, etc.

The problem is that when we tried to use the tiles inside our ol3 code (inside the web-system), the tiles are shifted eastward in respect to the basemap. It is not a projection problem, we deal with this on our ol3 code. I guess it come from the fact that for the first zoom, the generated tile presents margins (transparent, alpha), I mean, the image is not fitted on the bottom-left corner. To overcome the problem (provisionally, because it is not convenient), we modified the correct origin (more westward) up to the point when the tile fit to the basemap.

The strange thing is ol2 webviewer (automaticaly generated by gdal2tiles.py) seems to nicely deal with this "extra" space on margins, because the tiles viewed with openlayers.html do not present any shift.

here is the code to generate the tiles:

gdal2tiles.py -z 0-8 mygeotiff.tiff

here a screenshot of the 0/0.png tile to see extra space on bottom-left corner, and the tile viewed with openlayers.html (v2.12). No problem!

enter image description here

here is our ol3 code to use the tiles inside our web-system

    <!DOCTYPE html>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" href="http://openlayers.org/en/v3.18.2/css/ol.css" type="text/css">
        <script src="http://openlayers.org/en/v3.18.2/build/ol.js"></script>
    var resolutions = [156543.03390000000945, 78271.51695000000473, 39135.75847500000236, 19567.87923750000118, 9783.93961875000059, 4891.96980937500030, 2445.98490468750015, 1222.99245234375007, 611.49622617187504];
    var extent = ol.proj.transformExtent([-119.99800110000001, -77.49100082418495, -53.03354490678051, -18.38559910000000], "EPSG:4326", "EPSG:3857");
        //var origin = ol.proj.transform([-180, -85.049], "EPSG:4326", "EPSG:3857");
            var origin = [extent[0], extent[1]];
        function init() {
        // Layer with Tiles 
        var testLayer = new ol.layer.Tile({
            source:new ol.source.TileImage({
                extent: extent,
                tileGrid: new ol.tilegrid.TileGrid({
                    origin: origin,
                    resolutions: resolutions,                               
                        tileUrlFunction: function(coordinate) {

                                if (coordinate === null) return undefined;
                                var z = coordinate[0];
                                var x = coordinate[1];
                                var y = coordinate[2];
                                var url = './'+z+'/'+ x +'/'+y +'.png';
                                return url;
        var originLayer = new ol.layer.Vector({
            source:new ol.source.Vector()
        var area = ol.geom.Polygon.fromExtent(extent);
        var areaFeature = new ol.Feature({name:"test2", geometry:area});
            areaFeature.setStyle(new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: 'rgb(200,200,200)',
                    width: 2
            fill: null
        var punto = new ol.geom.Circle(origin, 200000);
        puntoFeature = new ol.Feature({name:"origen", geometry:punto});
        puntoFeature.setStyle(new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: 'yellow',
                width: 3
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.8)'
        var baseLayer = new ol.layer.Tile();
        baseLayer.setSource(new ol.source.OSM());
        this.mapa = new ol.Map({
            target: 'mapa',
            layers: [
                testLayer, originLayer
            view: new ol.View({
                center: ol.proj.fromLonLat([-74, -32]),
                        zoom: 7

    <body onload="init()">
        <h1>Test OL3</h1>
        <div id="mapa" style="width: 800px; height: 600px;"></div>

here is the tile viewed with our ol3 code. Eastward shifted !!. And the tile viewed with our ol3 code, but with the origin artificially westward shifted:

enter image description here

Additional information:

  • There is NO extra space on margins for our Geotiff !
  • We know that ol2 uses OpenLayers.Layer.TMS, but this is not available in ol3. Instead we use ol.layer.Tile with source TileImage (or XYZ)

How to deal with this shift (or extra space) on an ol3 code, without artificially changing the image's origin, or to avoid producing this extra space on gdal2tiles ?

It is an "academic Project" and we work only with opensource libraries.

For the sake of curiosity, when producing the same tile but with maptiler interface, the tile fits perfectly the bottom-left corner and there is no problem to view it with our ol3 code ...

  • Welcome to GIS SE! As a new user please take the Tour. Please edit your question to focus on just one question - as it stands now your question is too broad as it is asking too many questions. If you have more than one distinct question you can look at asking them separately
    – Midavalo
    Oct 12, 2016 at 17:47
  • 1
    Hi Midavalo, I have edited my questions. Now it is only one question with "likely" two solutions. Is it ok ?
    – Quim
    Oct 12, 2016 at 18:27
  • Why don't you use MapTiler if it runs well with your file out of the box?
    – MapTiler
    Oct 13, 2016 at 14:10
  • Hi @Klokan Technologies Gmb, thanks for your comment. Our web-system is structured in a way that we need to prepare tiles in a Linux shell environment. As far as I understood the maptiler shell environment is for a "pro" license. No budge for the time being.
    – Quim
    Oct 13, 2016 at 16:00

1 Answer 1


For TMS you should use a tileLoadFunction similar to this:

tileUrlFunction = function(tileCoord, pixelRatio, projection) { var min = 0; var max = urls.length - 1; var idx = Math.floor(Math.random() * (max - min + 1)) + min; var x, y, z; z = tileCoord[0]; x = tileCoord[1]; y = tileCoord[2] + (1 << z); return urls[idx] + z + '/' + x + '/' + y + '.png'; };

  • Hi @bartvde, thanks for you answer. We will try your solution and come back later to give a feedback.
    – Quim
    Oct 13, 2016 at 15:58
  • Hi @bartvde, we tried your suggestion, but unfortunately it did not solve the problem. Just shifted the picture southward ... (I cannot add more pictures to show the result). We are a bit lost on this problem.
    – Quim
    Oct 14, 2016 at 14:58
  • Can you share a jsFiddle? That would be a lot easier.
    – bartvde
    Oct 14, 2016 at 17:07
  • here is the jsFiddle link: jsfiddle.net/otrojota/s4vovwp3/6
    – Quim
    Oct 14, 2016 at 17:59
  • You can play by uncomment the var origin = ol.proj.transform([-180, -85.049], "EPSG:4326", "EPSG:3857");
    – Quim
    Oct 14, 2016 at 18:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.