Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kenji-miyake/811655fa1bb5cfdfc08aa1f21904820d to your computer and use it in GitHub Desktop.
Save kenji-miyake/811655fa1bb5cfdfc08aa1f21904820d to your computer and use it in GitHub Desktop.
How to generate XYZ tiles using QGIS3

How to generate XYZ tiles using QGIS3

Overview

QGIS3 has a tool called 'gdal2tiles.py' which can generate map tiles, but currently, it only supports TMS, not XYZ. However, QGIS3 loads XYZ by default and requires checkbox for TMS, so it's better to convert TMS to XYZ.

The difference between TMS and XYZ is just the name of Y-coordinate, so renaming works well. tms2xyz.py is a script for that.

Workflow

Suppose you have raster images with world files.

  1. Generate GeoTIFF files

This command converts an image to GeoTIFF. It's better to iterate files using shell script if you have many files.

gdal_translate -of GTiff -a_srs EPSG:{src-srs-number} {input-image-name} {output-tiff-name}

  1. Merge GeoTIFF files to one file

First, list up file names of .tiff files.

  • Windows: dir /B {tiff-dir-name}\*.tiff > list.txt
  • Linux: ls {tiff-dir-name} | grep '.tiff' > list.txt

Then, create VRT(Virtual Dataset). This is probably the fastest way to merge.

gdalbuildvrt -o merge.vrt -input_file_list list.txt

Finally, create a merged GeoTIFF file from VRT.

gdal_translate -ot Byte -co COMPRESS=LZW -co BIGTIFF=YES merge.vrt merge.tiff

  1. Convert GeoTIFF to tiles

This command converts the merged GeoTIFF file to TMS tiles.

gdal2tiles -r "bilinear" -s "EPSG:{src-srs-number}" -z "16-20" --processes=8 merge.tiff tms-tiles

  1. Convert TMS to XYZ

This command converts TMS tiles to XYZ tiles.

python tms2xyz.py tms-tiles xyz-tiles

See the following links for more options of GDAL commands.

References

import argparse
import shutil
from pathlib import Path
def tms2xyz(args):
for old_path in args.input_tms_dir.glob(f'**/*{args.ext}'):
z = int(old_path.parent.parent.stem)
x = int(old_path.parent.stem)
y = int(old_path.stem)
new_y = 2**z - y - 1
new_path = args.output_xyz_dir / str(z) / str(x) / (str(new_y) + args.ext)
if args.verbose:
print(f'{old_path} -> {new_path}')
if not args.dry_run:
new_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy(old_path, new_path)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Convert TMS tiles to XYZ tiles")
parser.add_argument('input_tms_dir', type=Path)
parser.add_argument('-o', '--output_xyz_dir', type=Path, default='./xyz-tiles')
parser.add_argument('-e', '--ext', default='.png')
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('--dry-run', action='store_true')
args = parser.parse_args()
tms2xyz(args)
@easz
Copy link

easz commented Jan 30, 2022

newer version of gdal2tiles has an option --xyz to generate XYZ tiles

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