Table of Contents
Raster con GDAL e MapServer
Raster type: Float32, Int16, Byte
La gestione dei raster Tiff con GDAL e MapServer non funziona sempre alla perfezione come si vorrebbe. Si deve fare sempre attenzione al tipo di raster con cui si ha a che fare, potrebbe trattarsi di Float32, Int16 oppure Byte.
Con gdalinfo
è possibile ottenere l'informazione, ecco alcuni esempi di output su raster costituiti da una singola banda:
Band 1 Block=2160x1 Type=Float32, ColorInterp=Gray NoData Value=-9999
Band 1 Block=2160x1 Type=Int16, ColorInterp=Gray NoData Value=-9999
Band 1 Block=64x64 Type=Byte, ColorInterp=Gray
La conversione con gdal_translate
- ad esempio dal formato Arc/Info ASCII Grid - potrebbe non indovinare il formato corretto, con il risultato di troncare alcuni valori.
Ecco come forzare l'utilizzo del tipo adeguato:
gdal_translate -of GTiff -ot Float32 minrainfal.asc minrainfal.tif gdal_translate -of GTiff -ot Int16 maxrainfal.asc maxrainfal.tif
Classificazione di raster con MapServer
Per ottimizzare la classificazione di un raster Float32 o Int16 con MapServer, conviene aggiungere le direttive per la gestione dei raster tramite LAYER.PROCESSING
, in particolare SCALE
e SCALE_BUCKETS
. Ecco un esempio in cui i valori compresi tra -55.0 e 45.0 vengono classificati in 24 classi:
LAYER NAME "temperature" PROCESSING "SCALE=-55.00,45.00" PROCESSING "SCALE_BUCKETS=24" CLASS NAME "< -50" EXPRESSION ([pixel] < -50.83) STYLE COLOR 0 53 255 END END CLASS NAME "-50 ÷ -46" EXPRESSION ([pixel] >= -50.83 and [pixel] < -46.67) STYLE COLOR 0 106 255 END END ...
Vedere in proposito MapServer Raster Data. Tali direttive non servono (anzi creano problemi) con raster a 8 bit.
Per verificare l'elaborazione del raster si può utilizzare shp2img
, in questo modo:
shp2img -m /path/to/file.map -all_debug 10 -o /path/to/raster ... msDrawRasterGDAL_16BitClassification(GEBCO): scaling to 8913 buckets from range=-5600.5,3312.5. ...
Ottimizzare raster con gdal_translate
Alcune caratteristiche di un file TIFF possono incidere sulle performance di MapServer. Su file molto grossi ad esempio la memorizzazione in blocchi (256×256) piuttosto che in righe di pixel può migliorare i tempi di accesso. Anche la compressione può incidere negativamente sulle prestazioni.
Ecco un comando che converte un file TIFF in un'altro file TIFF, l'organizzazione sarà a blocchi di 256×256 pixel e nessuna compressione. Le informazioni geografiche saranno memorizzate in un world file (.tfw) esterno:
gdal_translate -co TILED=YES -co TFW=YES -co COMPRESS=NONE src.tif dst.tif
Con gdalinfo
si potrà vedere il blocksize:
Band 1 Block=256x256 Type=Byte, ColorInterp=Palette
Georiferire un file PNG
Quei mattacchioni della NASA fanno scaricare il BlueMarble in formato PNG, non georiferito!
Bisognerebbe creare un world file secondo la struttura documentata da Georeference with World Files. Il problema è sapere i parametri! Per fortuna abbiamo un GeoTiff del TrueMarble alla stessa risoluzione e nello stesso sistema di riferimento, con gdalinfo
vediamo i parametri del GeoTiff:
gdalinfo TrueMarble.2km.21600x10800.tif ... Origin = (-180.000000000000000,90.000000000000000) Pixel Size = (0.016666666666667,-0.016666666666667) ...
Un trucco per creare il world file a partire da un GeoTiff usando i tool gdal è il seguente:
gdal_translate -co "TFW=YES" TrueMarble.2km.21600x10800.tif temp.tif mv temp.tfw TrueMarble.2km.21600x10800.tfw rm temp.tif
Creiamo il world file con lo stesso nome del file .png
, ma estensione .wld
oppure .tfw
(un world file con tale estensione viene trovato sia da MapServer che dalla libreria GDAL). Le coordinate del centro del pixel in alto a sinistra sono le cordinate dell'origine riportate da gdalinfo
, meno la metà di un pixel:
0.0166666667 0.0000000000 0.0000000000 -0.0166666667 -179.9916666667 89.9916666667
Peccato che la velocità di accesso non sia accettabile, il manuale di GDAL recita: PNG files are linearly compressed, so random reading of large PNG files can be very inefficient.
Una soluzione non ottimale è quella di convertire in Tiff non compresso con ImageMagick (il world file da usare rimane esattamente lo stesso):
convert world_topo_bathy.png -compress none world_topo_bathy.tif
La soluzione migliore è creare un GeoTiff completo, che non ha bisogno del world file perché incorpora tutte le informazioni geografiche necessarie. A tale scopo si può usare il comando:
gdal_translate -a_srs EPSG:4326 world_topo_bathy.png world_topo_bathy.tif
Nel GeoTiff risultante vengono incorporate sie le informazioni relative al sistema di riferimento che quelle contenute nel world file.
Overview Images (piramidi)
Se il file è troppo grande conviene creare le overview, dette anche piramidi, altrimenti uno zoom alla massima estensione obbliga a leggere e ridimensionare al volo tutto il raster.
In genere si generano delle copie dell'immagine con risoluzione 1/2, 1/4, 1/8, … dell'originale. Le overview possono essere contenute all'interno dello stesso GeoTiff:
gdaladdo TrueMarble.8km.5400x2700.tif 2 4 8
Se invece vogliamo tenere le overview in un file separato (che avrà estensione .tif.ovr
) ed utilizzare un algoritmo di ricampionamento migliore (gauss, ma anche average è migliore del nearest predefinito):
gdaladdo -ro -r gauss TrueMarble.8km.5400x2700.tif 2 4 8
Con le versioni di GDAL < 1.6.0 si deve usare una sintassi diversa, il file esterno con le overview avrà formato Erdas Image ed estensione .aux
:
gdaladdo --config USE_RRD YES TrueMarble.8km.5400x2700.tif 2 4 8
MapServer e la libreria Gdal accedono automaticamente alle overview anche se si trovano nel file separato .aux
.
Creare una overview di una copertura tiled
Anche se nelle tile sono state aggiunte le overview, ai fattori di scala maggiori (zoom minore) è necessario accedere a tutti i file (tile) della copertura per generare la mappa. Questo fa decadere di molto le prestazioni, è quindi opportuno creare una versione ridotta della copertura, contenuta in un singolo file.
Tale file conviene che sia TIFF memorizzato a blocchi ed eventualmente deve comprendere le overview opportune. Ecco come usare gdal_merge
per ottenere il risultato:
gdal_merge.py -o output.tif -of GTiff -co TILED=YES -co TFW=YES -ps 0.9765625 0.9765625 2001/*.jpg
La dimensione del pixel (in metri) viene calcolata dividento la larghezza della copertura per il numero di pixel desiderati. Ad esempio se si ha una superficie larga 16 km e si vuole creare un'immagine larga 16384 pixel:
(670510 - 654510) / 16384 = 0.9765625