Erzeugen mehrerer Auflösungen bei Tiff-Bildern (z.B. DOPs) mit WMS
--Markus Hentschel 15:59, 31. Mär 2010 (CEST)
Eine Alternative zum Bauen von Pyramiden im GeoTIFF selber: Bildkacheln erstellen für verschiedene Maßstabsstufen.
Die originalen Daten müssen als WMS erreichbar sein, dann kann man über den WMS Kacheln in beliebiger Größe und Auflösung erzeugen und als GeoTIFF speichern. Die Auflösungsstufen werden also nicht in jeder Kachel angelegt, sondern es entsteht ein Kachel-Set für jede Auflösungsstufe, allerdings mit immer weniger Bildern pro Stufe bis hin zu einem Bild für den ganzen Landkreis.
Hier zunächst mal das Script:
#!/bin/ksh # # Skript kachel_dop # Erstellt neue Kacheln mit anderer Auflösung und/oder Größe # über einen WMS des MapServers ####################################### # Variablendefinition # Auflösungsstufe scale="1" # Verzeichnis zum Speichern der neuen Kacheln relativ zum Speicherort des Skripts dest_dir="over${scale}" # Ziel-Koordinatensystem ziel_epsg=25833 # Definition des zu kachelnden Gebiets im Ziel-Koordinatensystem min_rechts=360000 # Rechtswert der Ecke links unten min_hoch=5982000 # Hochwert der Ecke links unten d_rechts=32000 # maximale Ausdehnung des Bereichs in Metern (min_rechts + d_rechts = Rechtswert rechts oben) d_hoch=56000 # maximale Ausdehnung des Bereichs in Metern (min_hoch + d_hoch = Hochwert rechts oben) # Definition der zu erzeugenden Kacheln pixel=1250 # Wert fuer Breite und Hoehe bbox=250 # Ist die Ausdehung der Boundingbox in Metern in Rechts- und Hochwert # Serveradresse und Mapdatei aufruf="http://servername/cgi-bin/mapserv?map=/pfad/zur/mapdatei.map&" # Layername aus der Mapdatei layers="Ortho2014" format="tiff" # tiff, png, jpeg extension="tif" # Dateiendung der zu erzeugenden Kacheln ####################################### # Wenn Vezeichnis bereits existiert, wird es vorher geloescht und neu angelegt: test -d ${dest_dir} && rm -r ${dest_dir} test -d ${dest_dir} || mkdir ${dest_dir} # Anlegen einer Datei namens "request" in die die Requests reingeschrieben werden (Logdatei) > $dest_dir/requests # äußere Schleife - erst die Zeilen von unten nach oben ... i=0 while [ $i -lt $d_hoch + $bbox ] do z2=$(($min_hoch + $i)) # innere Schleife - ... dann die Kacheln von links nach rechts j=0 while [ $j -lt $d_rechts + $bbox ] do z1=$(($min_rechts + $j)) z3=`expr $z1 + $bbox` z4=`expr $z2 + $bbox` wms="${aufruf}REQUEST=GetMap&VERSION=1.1.0&SERVICE=WMS&LAYERS=${layers}&STYLES=&SRS=EPSG:${ziel_epsg}&BBOX=${z1},${z2},${z3},${z4}&WIDTH=${pixel}&HEIGHT=${pixel}&BGCOLOR=0xffffff&TRANSPARENT=TRUE&FORMAT=image/${format}&EXCEPTIONS=application/vnd.ogc.se_xml" # Speichert das Bild im angegebenen Ordner wget -O ./${dest_dir}/${z1}_${z2}.${extension} $wms echo $wms >> $dest_dir/requests j=`expr $j + $bbox` # 8 bit Farbtiefe, kein Alpha-Kanal gdal_translate -ot Byte -scale -b 1 -b 2 -b 3 ./${dest_dir}/${z1}_${z2}.${extension} ./${dest_dir}/${z1}_${z2}_${scale}.${extension} # Original löschen rm ${dest_dir}/${z1}_${z2}.${extension} done # Ende innere Schleife i=`expr $i + $bbox` done # Ende äußere Schleife echo "fertig!" exit 0
- Es wird von folgender Verzeichnisstruktur ausgegangen:
+ Startordner (z.B. "/data/Ortho2014") + Ordner mit den Originaldaten (z.B. "/data/Ortho2014/ETRS89_2014_org") + Ordner für 1. Auflösungsstufe (z.B. "/data/Ortho2014/over1") + Ordner für 2. Auflösungsstufe (z.B. "/data/Ortho2014/over2") + Ordner für 3. Auflösungsstufe (z.B. "/data/Ortho2014/over1") usw.
- Das Script muss im Startordner liegen.
- Wenn die Bilder in ETRS89 gelagert sind und die Rechtswerte in den TFWs 8-stellig sind (macht das LaIV so), dann müssen sie um 2 Stellen gekürzt werden oder das muss in der Mapdatei berücksichtigt werden (nicht EPSG 25833, sondern 35833).
- Für die Originaldaten muss es einen Index-Shape (gdaltindex) und eine Mapdatei geben. Index-Shape ggfs. erst nach der TFW-Behandlung erstellen.
- Bevor es losgeht, empfiehlt es sich, sich einen genauen Überblick zu verschaffen. Dabei kann auch gleich ein netter Screenshot für die kvwmap-Benutzer abfallen:
- Dem Index-Shape mit einem geeigneten GIS-Werkzeug eine Spalte „id“ hinzufügen
- Der Spalte „ID“ einen fortlaufenden Wert zuweisen
- Übersichtslayer in kvwmap anlegen und in data auf den Index-Shape weisen
- Layer in der Karte vielleicht zusammen mit ORKA MV anzeigen
- Für den allerkleinsten Maßstabsbereich (von null bis ...) können die Original-Kacheln verwendet werden. Man sollte aber wegen der geringeren Dateigröße der Ergebnisdateien über das Script auch Kacheln erzeugen, die dieselbe Auflösung haben und dann an die Stelle der Originalbilder treten.
- Die Bild-Auflösung ergibt sich aus Kachelausdehnung in Metern geteilt durch Pixelanzahl. Beispiel: bei 2000 m und 10.000 Pixeln im Originalbild ergibt sich eine Auflösung von 0,2 Metern.
- Der Scalehint ist die Pixeldiagonale, also die Wurzel aus dem zweifachen Wert des Quadrats der Bild-Auflösung. Beispiel: bei einer Auflösung von 0,2 Meter ergibt sich ein Scalehint von 0,28284271
- Die untere Maßstabsgrenze für die Darstellung der Bilder in kvwmap ergibt sich aus folgender Formel:
Maßstab = Scalehint * dpi / 0.0254 / Wurzel aus 2 # 0.0254 = 1 Inch in Meter
- Für den untersten Maßstabsbereich wird davon abweichend allerdings bis runter auf Null gegangen (oder wo immer sich die untere Maßstabsgrenze des Layers befindet).
- Jetzt kann man sich eine Tabelle anlegen, in der man die Auflösungsstufen für das Script berechnet (und man erhält auch die Maßstabsstufen für die Mapdatei). Hier als Beispiel mit einer angenommenen Bildschirmauflösung von 91 dpi sowie mit einer Verdoppelung des Scalehints bei gleichbleibender Kachel-Pixelgröße von 1250 Pixeln (das kann man natürlich auch anders definieren):
Layer Pixel Kachel [m] Aufl. [m] Scalehint von bis [Maßstab 1:x bei 91 dpi] original 10000 2000 0,2 0,28284271 0 over1 1250 250 0,2 0,28284271 0 1433 over2 1250 500 0,4 0,56568542 1433 2866 over3 1250 1000 0,8 1,13137085 2866 5732 usw.
- Die mit diesen Werten erzeugten GeoTIFFs haben (bei Verwendung der von mir im Script vorgeschlagenen Parameter von gdal_translate) eine ungefähre Größe von ca. 4,5 MB.
- Für jede Auflösungsstufe wird das Script einzeln gestartet. Pro Bild benötigt mein Mapserver ca. 7 Sekunden, das kann je nach Server-Konfiguration natürlich variieren.
- Pro Durchgang müssen im Script die Werte dest_dir und bbox angepasst werden (pixel nur, wenn auch die Auflösung variieren soll). Außerdem ist jeweils der Layername aus der Mapdatei anzugeben (layers).
- Nach dem Durchlauf des Scripts wird über die erzeugte Auflösungsstufe ein Index-Shape erzeugt. Nur wenn die Index-Datei erfolgreich ohne Fehlermeldung angelegt wird, sind alle Kacheln erzeugt worden! Ansonsten fehlerhafte Kacheln einzeln (über das Script) in ein Extra-Verzeichnis erzeugen und dann ins heiße Verzeichnis verschieben
- In der Mapdatei einen neuen Layer anlegen und auf die neu erzeugte Index-Datei weisen.
- Nächster Durchgang bis hoch zu einem Bild für den ganzen Landkreis (wem das gefällt).
- Wenn sehr viele Kacheln erzeugt wurden, funktioniert der normale Aufruf von gdaltindex nicht mehr, weil es zu viele Argumente sind. Hier kann man so vorgehen:
find /data/Ortho2014/over1/ -name '*.tif' | xargs /usr/local/bin/gdaltindex /pfad/zum/vector-Verzeichnis/2014_over1.shp
- Jeder Durchgang baut immer auf den Kacheln des vorherigen Durchgangs auf. Das kann aber auch anders machen, z.B. die ersten Auflösungsstufen aus den Originalbildern usw. Allerdings führt das zu längeren Rendering-Zeiten beim Erstellen der Kacheln.
- Da der Landkreis selten ein perfektes Rechteck ist, entstehen eine Menge leerer Kacheln, was deutliche Auswirkungen auf den Speicherplatz und die Laufzeit des Scripts hat. Es lohnt sich, im Script ein wenig umzubauen: mehrere Durchläufe der Schleife, wobei die Definition des Rechtecks in die Schleife gezogen wird. Dann kann man den Landkreis in mehrere Rechtecke unterteilen und erhält auf diese Weise nicht soviel Datenmüll. Bei den höheren Auflösungsstufen kann man dann allerdings wieder auf ein Gesamt-Rechteck zurückgehen.
- Die Mapdatei wird nach Fertigstellung aller Auflösungsstufen für den kvwmap-Layer verwendet, der die Bilder anzeigen soll.
--Markus Hentschel 08:19, 14. Apr 2010 (CEST) Wenn man für andere Anwendungen TFW-Dateien benötigt, kann man das mit folgendem Script bewerkstelligen, das man aber auch ebensogut in das obige Script einbauen kann:
#!/bin/sh cd /data/Ortho2014/over1/ for FILE in *.tif do BASENAME=$(basename $FILE .tif) echo "Processing: ${BASENAME}.tif" gdal_translate -co "TFW=YES" $FILE ${BASENAME}_out.tif mv ${BASENAME}_out.tfw ${BASENAME}.tfw rm ${BASENAME}_out.tif done exit 0
Das nutzt allerdings nix, wenn man die TFWs z.B. für die ALK-Auskunft vom LaIV benötigt. Dieses Programm erwartet nämlich einen 8-stelligen Rechtswert ;-) Da hilft nur Massenweises Ändern von TFWs im Eastwert.
Dank an Markus Weißmann!