Erzeugen mehrerer Auflösungen bei Tiff-Bildern (z.B. DOPs) mit WMS

Aus kvwmap
Wechseln zu: Navigation, Suche

--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!