I have a bunch of aerial-like imagery:

  • each image/tile is a (1000,1000) (pixels) numpy array
  • each covers a 50x50 meters area
  • I know the origin's tile lat/lng coordinates so I can figure out the rest coordinates

How can I create raster tiles in a slippy map tilenames format (/{z}/{x}/{y}.jpg)?
I need to display them in a mapbox gl js app
Preferably in a python script as these images will be updated from time to time..

1 Answer 1


First you need to decide at which zoom level you want your mercator (slippy-map) tiles. Usually for javascript apps if you want your tiles loaded as basemap with multiple interactive zoom levels, you will have to prepare the tiles corresponding to different zoom levels. You can do this preparation in-memory on the serverside when the request is received or you can do it before hand and keep the tiles at different zoom levels ready and host the already prepared tiles through a /{z}/{x}/{y} map tile service.

Assuming that you have a raster with known bounding box corners in (lon,lat) format, you need to have calculate the west,south,east,north corners handy with you.

Once you have this you can use a python package like Mercantile, which accepts a bounding box and returns mercator tiles calculated at different zoom levels

tiles = list(mercantile.tiles(west, south, east, north, zoom))

then you can iterate over list of tiles at given zoom level(z) and get their mercator(slippy-map) x,y values for each tile like this.

for tile in tiles:
   z,x,y = tile.z,tile.x,tile.y
   tile_west,tile_south,tile_east,tile_north = mercantile.bounds(tile)

This way you get the z,x,y of every tile at a particular zoom level and you also get bounds for tiles at that zoom level. Use the bounds obtained to crop or stitch your rasters to produce rasters corresponding to the tile at that zoom level.

In your case the rasters you have are 50 meters x 50 meters so if you want to produce the rasters at lower zoom level like a level 14 or 15, you will have to stitch your multiple rasters to produce the raster at that zoom level.

If your original raster would have been larger and you would want to produce tiles at higher zoom level like level 21, you would need to crop your raster to produce smaller tiles by calculating the bounding box for each tile at zoom level 21.

Once you have tiles produced at different zoom levels, host it via an REST API so that the path {z}/{x}/{y} corresponds to the tile prepared at that zoom level for the given x and y value.

  • Great answer, thank you very much! Regadring stitching/cropping - how should I approach that? PIL/pillow? or should I manipulate my numpy arrays before actually saving them as images? Is there any library that can help with that use case? I guess it's kinda common..
    – Atias
    Jul 31, 2022 at 15:18
  • You can concatenate the numpy arrays together. For e.g. if you have generated level 21 tiles by cropping your original images you can derive level 20 tiles by stitching 4 adjacent level 21 tiles and similarly derive level 19 tiles by stitching 4 adjacent level 20 tiles and likewise.
    – Abhilshit
    Aug 1, 2022 at 18:09

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.