Skip to content

Instantly share code, notes, and snippets.

@jsoctocat
Last active March 9, 2026 07:21
Show Gist options
  • Select an option

  • Save jsoctocat/81833b3a8bef0edc80f6a5a2ce403fbf to your computer and use it in GitHub Desktop.

Select an option

Save jsoctocat/81833b3a8bef0edc80f6a5a2ce403fbf to your computer and use it in GitHub Desktop.
import os
import shutil
from PIL import Image
from collections import defaultdict
input_folder = "minimap_data"
input_dir = f"./stitched_{input_folder}"
output_dir = "./stitched4leaflet"
tile_size = 256
output_size = 512
MAX_Z = 8
MIN_Z = 0
os.makedirs(output_dir, exist_ok=True)
# Maximum tile coordinates
max_x = 0 # x in range
max_y = 0 # y in range
for file in os.listdir(input_dir):
base = file.rsplit(".", 1)[0] # remove extension
_, x, y = base.split("_")
max_x = max(max_x, int(x))
max_y = max(max_y, int(y))
# First step is to create the leaflet folder structure and then move the most zoomed in tiles into the highest Z
# Second step is to create zoomed out leaflet folder structures and tiles
for x in range(0, max_x + 1, 1):
for y in range(0, max_y + 1, 1):
tile_name = f"tile_{x}_{y}.webp"
tile_path = os.path.join(input_dir, tile_name)
if os.path.exists(tile_path):
os.makedirs(f"{output_dir}/{MAX_Z-1}/{x}", exist_ok=True)
shutil.copy2(tile_path, f"{output_dir}/{MAX_Z-1}/{x}/{y}.webp")
# Skip the first Z due to it being max zoomed and that's already created as the base
for z in range(MAX_Z-1, MIN_Z, -1):
groups = defaultdict(list)
for x in os.listdir(f"{output_dir}/{z}"):
for yfile in os.listdir(f"{output_dir}/{z}/{x}"):
y = int(yfile.replace(".webp",""))
nx, ny = int(x)//2, y//2
groups[(nx,ny)].append(f"{output_dir}/{z}/{x}/{yfile}")
for (nx,ny), files in groups.items():
os.makedirs(f"{output_dir}/{z-1}/{nx}", exist_ok=True)
canvas = Image.new("RGBA",(output_size,output_size),(0,0,0,0))
for f in files:
img = Image.open(f).convert("RGBA")
px = int(f.split("/")[-2]) % 2
py = int(f.split("/")[-1].replace(".webp","")) % 2
canvas.paste(img,(px*tile_size,py*tile_size))
canvas.resize((tile_size,tile_size),Image.BILINEAR)\
.save(f"{output_dir}/{z-1}/{nx}/{ny}.webp", "WEBP", quality=82, method=6)
print(f"Processed: {output_dir}/{z-1}/{nx}/{ny}.webp")
print("Batch processing complete.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment