Instantly share code, notes, and snippets.

Embed
What would you like to do?
The difference between XYZ and TMS tiles and how to convert between them

The difference between XYZ and TMS tiles and how to convert between them

Lots of tile-based maps use either the XYZ or TMS scheme. These are the maps that have tiles ending in /0/0/0.png or something. Sometimes if it's a script, it'll look like &z=0&y=0&x=0 instead. Anyway, these are usually maps in Spherical Mercator.

Good examples are OpenStreetMap, Google Maps, MapBox, MapQuest, etc. Lots of maps.

Most of those are in XYZ. The best documentation for that is slippy map tilenames on the OSM Wiki, and Klokan's Tiles a la Google.

Some of them are in TMS instead. TMS is an OSGeo spec. Here's the wiki page on it. It's less popular and few services support the whole spec.

There are no advantages of XYZ over TMS or vice-versa for most maps*, but XYZ is more popular.

Converting

Let's get to the point. The only difference between the two is a flipped y coordinate.

In math:

y = (2^z) - y - 1

javascript

y = Math.pow(2, z) - y - 1;

php

y = pow(2, z) - y - 1;

python

y = (2 ** z) - y - 1

ruby

y = (2 ** z) - y - 1

Addendum

When I say 'no difference' or 'no advantage' I mean for most maps. If you have some weird projection, use TMS but ideally don't make a tiled map in a weird projection in the first place. If you're forced to use OSGeo standards, do that but try to find a different job.

This originally credited OGC with TMS. It was OSGeo. OGC has WMTS. Don't use that either.

@yhahn

This comment has been minimized.

Show comment
Hide comment
@yhahn

yhahn Feb 15, 2013

Can you tell this in parable form?

yhahn commented Feb 15, 2013

Can you tell this in parable form?

@perrygeo

This comment has been minimized.

Show comment
Hide comment
@perrygeo

perrygeo Feb 15, 2013

"some weird projection" ... you mean that weird one where Greenland appears to be the size of Africa? Oh wait... :-)

If you're working on projects where equal area is critical, where equal distances matter, where the world view does not match that of Mercator, or anything in the polar regions, you've got no choice but to be weird.

perrygeo commented Feb 15, 2013

"some weird projection" ... you mean that weird one where Greenland appears to be the size of Africa? Oh wait... :-)

If you're working on projects where equal area is critical, where equal distances matter, where the world view does not match that of Mercator, or anything in the polar regions, you've got no choice but to be weird.

@kannes

This comment has been minimized.

Show comment
Hide comment
@kannes

kannes Nov 13, 2014

Thanks! I made a bash script to rename TMS files to XYZ as I already created them with gdal2tiles.py without noticing early on. https://gist.github.com/kannes/ebfe021458f96e4f30b5

It's probably super ugly because it spawns bash once per tile but hey, it works for me. ~1 minute for ~17000 files.

kannes commented Nov 13, 2014

Thanks! I made a bash script to rename TMS files to XYZ as I already created them with gdal2tiles.py without noticing early on. https://gist.github.com/kannes/ebfe021458f96e4f30b5

It's probably super ugly because it spawns bash once per tile but hey, it works for me. ~1 minute for ~17000 files.

@popkinj

This comment has been minimized.

Show comment
Hide comment
@popkinj

popkinj Jan 21, 2015

Awesome. Thanks for this Tom ☺.

popkinj commented Jan 21, 2015

Awesome. Thanks for this Tom ☺.

@MikeGodin

This comment has been minimized.

Show comment
Hide comment
@MikeGodin

MikeGodin Jul 30, 2015

Just a note that in a lot of languages, a binary left shift is much faster than floating point math for getting 2^z. For example, in Javascript, the function would be:

y = (1 << z) - y - 1;

MikeGodin commented Jul 30, 2015

Just a note that in a lot of languages, a binary left shift is much faster than floating point math for getting 2^z. For example, in Javascript, the function would be:

y = (1 << z) - y - 1;
@hastebrot

This comment has been minimized.

Show comment
Hide comment
@hastebrot

hastebrot Sep 10, 2015

Thank you so much!

Klokan's great example also gives some links for the tile addressing systems:

Update: Google Code link is gone. Maybe these links are a replacement:

hastebrot commented Sep 10, 2015

Thank you so much!

Klokan's great example also gives some links for the tile addressing systems:

Update: Google Code link is gone. Maybe these links are a replacement:

@spyhunter99

This comment has been minimized.

Show comment
Hide comment
@spyhunter99

spyhunter99 May 26, 2016

are the equations above for converted from XYZ to TMS or vice verse?

spyhunter99 commented May 26, 2016

are the equations above for converted from XYZ to TMS or vice verse?

@Bibi56

This comment has been minimized.

Show comment
Hide comment
@Bibi56

Bibi56 Sep 28, 2016

@spyhunter99,
let call y_tms and y_xyz for clarification.
Let's say the equation is
y_tms = (1 << z) - y_xyz - 1
add (y_xyz - y_tms) to both sides of the equation.
Now you've
y_xyz = (1 << z) - y_tms - 1.
Pretty much the same isn't it?

Bibi56 commented Sep 28, 2016

@spyhunter99,
let call y_tms and y_xyz for clarification.
Let's say the equation is
y_tms = (1 << z) - y_xyz - 1
add (y_xyz - y_tms) to both sides of the equation.
Now you've
y_xyz = (1 << z) - y_tms - 1.
Pretty much the same isn't it?

@jrvanderveen

This comment has been minimized.

Show comment
Hide comment
@jrvanderveen

jrvanderveen Nov 12, 2016

So im using gdal2tiles.py to tile a raster into a TMS but the software im using to display this uses XYZ scheme. Ive tested this math on my files and maybe im missing something but it gives me the wrong file names. For instance I want to convert level 4 aka z = 4, this folder has 8 x coordinate folders with 7 y coordinate png in them. I want the ...4/0/6.png to equal ...4/0/0.png and so on. y_xyz = 2^4 - 6 - 1 = 9. Am i missing something here? To get the right conversion I do y_xyz = 2^4 - 6 - 1 - (2^z - 1 - ymax)

jrvanderveen commented Nov 12, 2016

So im using gdal2tiles.py to tile a raster into a TMS but the software im using to display this uses XYZ scheme. Ive tested this math on my files and maybe im missing something but it gives me the wrong file names. For instance I want to convert level 4 aka z = 4, this folder has 8 x coordinate folders with 7 y coordinate png in them. I want the ...4/0/6.png to equal ...4/0/0.png and so on. y_xyz = 2^4 - 6 - 1 = 9. Am i missing something here? To get the right conversion I do y_xyz = 2^4 - 6 - 1 - (2^z - 1 - ymax)

@Murthy10

This comment has been minimized.

Show comment
Hide comment
@Murthy10

Murthy10 Apr 25, 2017

Have a look at https://github.com/geometalab/pyGeoTile, it solves this problem and is available as PyPi package.

pip install pyGeoTile

Murthy10 commented Apr 25, 2017

Have a look at https://github.com/geometalab/pyGeoTile, it solves this problem and is available as PyPi package.

pip install pyGeoTile

@haggaishG

This comment has been minimized.

Show comment
Hide comment
@haggaishG

haggaishG Oct 16, 2018

Fantastic article. Helped me a lot.
Please note that for for the tile index you may need to adjust with Math.floor(Math.pow(2, z) - y - 1)

haggaishG commented Oct 16, 2018

Fantastic article. Helped me a lot.
Please note that for for the tile index you may need to adjust with Math.floor(Math.pow(2, z) - y - 1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment