60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
import time
|
|
import urllib.error
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
from .coords import SLICE, TILE_PX, mosaic_origin_px, slice_tiles
|
|
|
|
COMMIT = "4093e8c874e480d47c38b37fe7a404f8b0c5275e"
|
|
BASE = f"https://raw.githubusercontent.com/rolux/gtadb.org/{COMMIT}/maps/tiles/6/yanis%2C15/5"
|
|
UA = {"User-Agent": "leonida-extract/0.1 (local hobby project)"}
|
|
|
|
|
|
def download_tiles(cache: Path) -> None:
|
|
"""Lädt alle Kacheln des Ausschnitts; vorhandene werden übersprungen."""
|
|
cache.mkdir(parents=True, exist_ok=True)
|
|
missing = []
|
|
for row, col in slice_tiles():
|
|
name = f"5,{row},{col}.jpg"
|
|
dst = cache / name
|
|
if dst.exists():
|
|
continue
|
|
for attempt in range(3):
|
|
try:
|
|
req = urllib.request.Request(f"{BASE}/{name}", headers=UA)
|
|
dst.write_bytes(urllib.request.urlopen(req, timeout=30).read())
|
|
break
|
|
except (urllib.error.URLError, TimeoutError):
|
|
time.sleep(2 ** attempt)
|
|
else:
|
|
missing.append(name)
|
|
if missing:
|
|
raise RuntimeError(f"{len(missing)} Kacheln fehlen: {missing[:5]} ...")
|
|
|
|
|
|
def assemble(load_tile) -> np.ndarray:
|
|
"""Setzt die Kacheln zusammen und schneidet auf den Ausschnitt zu."""
|
|
tiles = slice_tiles()
|
|
r0 = min(r for r, _ in tiles)
|
|
c0 = min(c for _, c in tiles)
|
|
rows = max(r for r, _ in tiles) - r0 + 1
|
|
cols = max(c for _, c in tiles) - c0 + 1
|
|
full = np.zeros((rows * TILE_PX, cols * TILE_PX, 3), dtype=np.uint8)
|
|
for row, col in tiles:
|
|
y, x = (row - r0) * TILE_PX, (col - c0) * TILE_PX
|
|
full[y:y + TILE_PX, x:x + TILE_PX] = load_tile(row, col)
|
|
ox, oy = mosaic_origin_px()
|
|
w = SLICE["x1"] - SLICE["x0"]
|
|
h = SLICE["y1"] - SLICE["y0"]
|
|
return full[oy:oy + h, ox:ox + w]
|
|
|
|
|
|
def load_mosaic(cache: Path) -> np.ndarray:
|
|
def load_tile(row: int, col: int) -> np.ndarray:
|
|
with Image.open(cache / f"5,{row},{col}.jpg") as img:
|
|
return np.asarray(img.convert("RGB"))
|
|
return assemble(load_tile)
|