96 lines
2.9 KiB
Python
96 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import sys
|
|
import mercantile
|
|
import numpy as np
|
|
from rio_tiler.io import COGReader
|
|
from rio_tiler.utils import render
|
|
|
|
# ---------------------------------------------------------
|
|
# USO:
|
|
# python3 make_tiles_rio_tiler.py input_rgb.tif tiles_out/
|
|
#
|
|
# Versione finale:
|
|
# - BUFFER per evitare buchi tra quadranti
|
|
# - PADDING per generare tile anche se il TIFF copre solo parte della tile
|
|
# - Logging avanzato
|
|
# - Controllo tile vuote
|
|
# ---------------------------------------------------------
|
|
|
|
ZOOM_MIN = 5
|
|
ZOOM_MAX = 14
|
|
BUFFER = 0.005 # espansione bounds per evitare tile mancanti
|
|
TILESIZE = 256 # tile standard
|
|
PADDING = 1 # genera tile anche se parziali
|
|
|
|
def generate_tiles(input_tif, output_dir):
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
|
|
print(f"\n=== Generazione tile per: {input_tif} ===")
|
|
print(f"Zoom: {ZOOM_MIN}..{ZOOM_MAX}")
|
|
print(f"Buffer: {BUFFER}°")
|
|
print(f"Padding: {PADDING} pixel\n")
|
|
|
|
with COGReader(input_tif) as cog:
|
|
|
|
for z in range(ZOOM_MIN, ZOOM_MAX + 1):
|
|
print(f"\n== Zoom {z} ==")
|
|
|
|
# Bounds originali del TIFF
|
|
bounds = cog.bounds
|
|
|
|
# Espansione per evitare buchi tra quadranti
|
|
minx = bounds[0] - BUFFER
|
|
miny = bounds[1] - BUFFER
|
|
maxx = bounds[2] + BUFFER
|
|
maxy = bounds[3] + BUFFER
|
|
|
|
# Tile da generare
|
|
tiles = list(mercantile.tiles(minx, miny, maxx, maxy, z))
|
|
print(f"Tile da generare: {len(tiles)}")
|
|
|
|
for t in tiles:
|
|
out_dir_zxy = os.path.join(output_dir, str(z), str(t.x))
|
|
os.makedirs(out_dir_zxy, exist_ok=True)
|
|
out_path = os.path.join(out_dir_zxy, f"{t.y}.png")
|
|
|
|
try:
|
|
tile, mask = cog.tile(
|
|
t.x, t.y, z,
|
|
tilesize=TILESIZE,
|
|
padding=PADDING,
|
|
resampling_method="nearest"
|
|
)
|
|
except Exception as e:
|
|
print(f" ⚠️ Errore tile {z}/{t.x}/{t.y}: {e}")
|
|
continue
|
|
|
|
# Controllo tile vuote (tutto zero o tutto trasparente)
|
|
if mask is not None and np.all(mask == 0):
|
|
print(f" ⚠️ Tile vuota saltata: {z}/{t.x}/{t.y}")
|
|
continue
|
|
|
|
img = render(tile, mask=mask, img_format="PNG")
|
|
|
|
with open(out_path, "wb") as f:
|
|
f.write(img)
|
|
|
|
print(f" ✓ {z}/{t.x}/{t.y}")
|
|
|
|
print("\n=== Completato senza errori ===\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 3:
|
|
print("Uso: python3 make_tiles_rio_tiler.py <input_rgb.tif> <output_dir>")
|
|
sys.exit(1)
|
|
|
|
INPUT_TIF = sys.argv[1]
|
|
OUTPUT_DIR = sys.argv[2]
|
|
|
|
if not os.path.isfile(INPUT_TIF):
|
|
print(f"Errore: file non trovato: {INPUT_TIF}")
|
|
sys.exit(1)
|
|
|
|
generate_tiles(INPUT_TIF, OUTPUT_DIR)
|
|
|