Borner le comblement du MNT à l'enveloppe des points, ajouter la couche précision et un affichage relief/précision, encoder les sous-tuiles une seule fois en q75
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -160,8 +160,20 @@ COLORMAPS = {
|
||||
'vmin_mode': 'fixed', 'vmin_val': 0,
|
||||
'vmax_mode': 'fixed', 'vmax_val': 1,
|
||||
},
|
||||
# Densité de points sol : niveau 0..15 (visualizations.density_levels)
|
||||
'densite_sol': {
|
||||
'cmap': 'gray',
|
||||
'vmin_mode': 'fixed', 'vmin_val': 0,
|
||||
'vmax_mode': 'fixed', 'vmax_val': 15,
|
||||
},
|
||||
}
|
||||
|
||||
# Couches en aplats de gris codés (niveaux discrets) : image niveaux de gris
|
||||
# (mode L) encodée SANS PERTE (AVIF q100 en L, seul réglage exact) — l'AVIF q55-60 déplace ~20 % des pixels jusqu'à 4
|
||||
# niveaux sur ces aplats. Elles restent à leur résolution propre (1 m pour
|
||||
# la densité : ~150–260 Ko par dalle).
|
||||
LOSSLESS_GRAY_KEYWORDS = ('densite_sol',)
|
||||
|
||||
# RGB entries (ortho/topo) are handled specially
|
||||
RGB_LEGENDS = {
|
||||
'ortho': {},
|
||||
@ -824,7 +836,24 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
|
||||
return None
|
||||
|
||||
|
||||
def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=60, output_format='avif'):
|
||||
def _write_subtiles_from(img, tif_file, vis_dir, resolution, subtiles_dir):
|
||||
"""Sous-tuiles d'une dalle depuis son image d'origine (best-effort :
|
||||
en cas d'échec, build_index les découpera depuis la dalle)."""
|
||||
from .index import VIZ_LABELS, _subdivision_k, write_subtiles
|
||||
try:
|
||||
k = _subdivision_k(resolution)
|
||||
stem = Path(tif_file).stem
|
||||
viz_key = next((v for v in sorted(VIZ_LABELS, key=len, reverse=True)
|
||||
if stem.endswith(f"_{v}")), None)
|
||||
if k <= 1 or viz_key is None:
|
||||
return
|
||||
write_subtiles(subtiles_dir, Path(vis_dir).name, viz_key, img, k)
|
||||
except Exception as e:
|
||||
logger.warning(f" Sous-tuiles non écrites ({Path(tif_file).name}) : {e}")
|
||||
|
||||
|
||||
def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=60, output_format='avif',
|
||||
subtiles_dir=None):
|
||||
"""Convert GeoTIFF to a cropped visualization image (no legend, no overlay).
|
||||
|
||||
Applies colormap and saves the image as a pure 1×1 km square.
|
||||
@ -837,6 +866,9 @@ def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=60, outpu
|
||||
keep_tif: If True, keep the source TIFF after conversion.
|
||||
quality: Image quality (1-100). Use 100 for lossless.
|
||||
output_format: Output format ('webp' or 'avif').
|
||||
subtiles_dir: dossier de sortie du pipeline : les sous-tuiles de la
|
||||
carte (index_subtiles) y sont écrites depuis l'image d'origine,
|
||||
un seul encodage avec perte (build_index les trouve à jour).
|
||||
|
||||
Returns:
|
||||
Path to output image file, or None on failure.
|
||||
@ -844,7 +876,8 @@ def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=60, outpu
|
||||
if not tif_file or not tif_file.exists():
|
||||
return None
|
||||
|
||||
ext = 'avif' if output_format == 'avif' else 'webp'
|
||||
lossless_gray = any(k in tif_file.stem for k in LOSSLESS_GRAY_KEYWORDS)
|
||||
ext = 'webp' if lossless_gray else ('avif' if output_format == 'avif' else 'webp')
|
||||
output_file = vis_dir / f"{tif_file.stem}.{ext}"
|
||||
|
||||
try:
|
||||
@ -892,12 +925,22 @@ def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=60, outpu
|
||||
# Save as AVIF/WebP
|
||||
img = PILImage.fromarray(rgb_data)
|
||||
pil_format = 'AVIF' if output_format == 'avif' else 'WEBP'
|
||||
if quality >= 100:
|
||||
if lossless_gray:
|
||||
# WebP sans perte en niveaux de gris : exact et 3× plus léger que
|
||||
# l'AVIF q100 (Pillow ignore `lossless=True` en AVIF : q75 avec perte)
|
||||
img = PILImage.fromarray(rgb_data[:, :, 0])
|
||||
img.save(str(output_file), format='WEBP', lossless=True)
|
||||
elif quality >= 100:
|
||||
img.save(str(output_file), format=pil_format, lossless=True)
|
||||
else:
|
||||
img.save(str(output_file), format=pil_format, quality=quality,
|
||||
**({'speed': AVIF_SPEED} if pil_format == 'AVIF' else {}))
|
||||
|
||||
# Sous-tuiles de la carte depuis l'image d'origine (après la dalle :
|
||||
# plus récentes qu'elle, build_index ne les ré-encode pas)
|
||||
if subtiles_dir is not None:
|
||||
_write_subtiles_from(img, tif_file, vis_dir, resolution, subtiles_dir)
|
||||
|
||||
# Delete source TIFF (unless --keep-tif)
|
||||
if not keep_tif:
|
||||
tif_file.unlink(missing_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user