03. Mai 2023

Leaflet-Karten mit gdal2tiles und QGis erstellen

Gepostet am 03. Mai 2023  •  6 Minuten  • 1196 Wörter

Für spezielle Karten und Overlays habe ich jahrelang MapTiler verwendet. Ich war auch ganz zufrieden damit, bis die Firma im letzten Jahr ihre Lizenzbedingungen geändert hat und nun statt 15 USD im Jahr satte 25 USD im Monat will. Da habe ich mich nach einer Open Source-Alternative umgesehen und diese stelle ich kurz vor.

Warum eigene Karten erstellen?

Ich habe immer wieder Mal den Fall, dass ich gerne eigene Karten wie OpenStreetMap oder Google Maps erstellen will. Ich denke, das geht nicht nur mir so. Beispiele für eigene Karten sind:

Grundlage aller genannter Use Cases ist, dass man Karten als großes Bild vorliegen hat (oder als PDF). Für das Web ist es jedoch besser, diese großen Bilder in viele kleine zu zerstückeln und mittels eines Tile Servers bzw. Kartenservers zur Verfügung zu stellen. Das spart Bandbreite und ermöglicht ein schöneres Zoom-Erlebnis. Außerdem kann es bei großen Karten vorkommen, dass Browser an ihre Grenzen kommen (habe ich tatsächlich schon erlebt).

Die Herausforderung - Bild zerteilen

Ich gehe davon aus, dass wir ein großes Bild vorliegen haben. Groß in diesem Fall ist mehr als 1000 Pixel Höhe und Breite, vermutlich eher mehrere tausend Pixel. Hat man ein PDF als Ausgangsformat muss man dieses zunächst in ein Bild konvertieren. Dazu gibt es eine Menge guter Hinweise im Internet (z.B. Gimp, ImageMagick/GraphicsMagick, Master PDF Editor, diverse Online-Tools, usw.), ich gehe hier nicht weiter darauf ein. Das Endformat ist relativ egal, sinnvoll ist hier JPG oder PNG.

Kartenserver wie OpenStreetMap oder Google Maps funktionieren folgendermaßen: Man startet mit einer bestimmten Zoom-Stufe - der Kachselserver hat für diese Stufe das große Bild (oder eben eine Weltkarte) in viele kleine Kacheln zerteilt, die in der Regel 256 oder 512 Pixel pro Seite groß sind. Zoomt man weiter in die Karte hinein, werden Kacheln einer anderen Zoom-Stufe aufgerufen, die mehr Details zeigen. Umgekehrt werden bei einer größeren Ansicht Kacheln gezeigt, die weniger Details zeigen. Das bedeutet auch, dass in der größten Zoom-Stufe ziemlich viele Kacheln vorliegen müssen (zumindest bei einer Weltkarte).

Idealerweise soll das große Bild zoombar sein

Das Erstellen von Kacheln aus einem Bild ist weniger einfach als gedacht - die meisten Anleitungen im Internet gehen davon aus, dass man Bilder oder Overlays auf eine Weltkarte projizieren will. Das ist auch cool, aber in diesem Artikel will ich ein Bild als Karte verwenden.

Als Beispiel habe ich mir eine Karte über Azgaar’s Fantasy Map Generator generieren lassen. Diese ist 15992x8472 Pixel groß und damit ein gutes Beispiel. Die Karte kann hier angezeigt/heruntergeladen werden .

Möglichkeit 1: gdal2tiles.py

Zum Zerteilen gibt es mehrere Möglichkeiten. Die meisten arbeiten im Hintergrund mit gdal , einer Programmbibliothek für Kartentransformation und -bearbeitung. Das Python-Programm gdal2tiles.py ist ein Kommandozeilen-Programm, das diese Bibliothek benutzt. Es gibt dummerweise eine ganze Reihe von Varianten und Versionen, was die Benutzung etwas verwirrend macht, da die Programmparameter in einer Version nicht zwingend jene sein müssen, die in der anderen Version funktionieren.

Ich verwende die Version von der GitHub-Seite https://github.com/commenthol/gdal2tiles-leaflet - diese ist gut mit Leaflet zu verwenden, auf das ich weiter unten eingehen werde.

Man kann die Quelldateien via GitHub herunterladen oder mithilfe von git clone https://github.com/commenthol/gdal2tiles-leaflet, sofern man git installiert hat. Python 3 sollte ebenfalls auf dem System installiert sein. Nun muss man die gdal-Bibliothek installieren, was auf Debian-basierten System mittels sudo apt install python3-gdal funktioniert.

Nun wechselt man in das entsprechende Verzeichnis, lädt die Beispieldatei herunter und konvertiert sie in Kacheln. Hier das gesamte Beispiel:

# gdal mit python bindings installieren
sudo apt install python3-gdal

# Projekt klonen
git clone https://github.com/commenthol/gdal2tiles-leaflet
cd gdal2tiles-leaflet

# Karte herunterladen
wget https://www.auxnet.de/downloads/example-map.jpg

# Karte konvertieren
python3 gdal2tiles.py -l -p raster -w none example-map.jpg example-map

Anmerkung: Hat man eine PNG-Karte als Ausgangsbasis muss diese in 8 Bit konvertiert werden! Das einfachste ist es, die Karte in Gimp zu laden und als PNG (8-Bit Farbtiefe) wieder zu exportieren.

Im Verzeichnis example-map liegen die Tiles. Diese wollen wir nun anzeigen (mit Leaflet ). Dazu erstellen wir folgende HTML-Datei (index.html) im aktuellen gdal2tiles-leaflet-Verzeichnis:

<html lang="de">
  <head>
    <title>Testkarte</title>
    <meta charset="utf-8">
    <link
      rel="stylesheet"
      href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
      integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
      crossorigin=""
    />
    <script
      src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
      integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
      crossorigin=""
    ></script>
  </head>
  <body style="margin: 0; padding: 0">
    <div id="map" style="height: 100vh; width: 100vw"></div>

    <script>
      const map = L.map("map", {
        crs: L.CRS.Simple,
        minZoom: 0,
        maxZoom: 6,
      }).setView([-50, 100], 4);
      L.tileLayer("/example-map/{z}/{x}/{y}.jpg", {
        tileSize: 256,
        crs: L.CRS.Simple,
      }).addTo(map);
    </script>
  </body>
</html>

Wichtig ist hier:

Die Karte lässt sich mithilfe eines Webservers anzeigen. Ein einfacher Server, den ich für ein anderes Projekt geschrieben habe, ist Go Fyne Webserver . Diesen kann man für seine Plattform (Linux, Windows, MacOS) herunterladen und einfach starten (auf unixoiden Systemen muss man die Datei noch als ausführbar definieren). Vor dem Start kann man das korrekte Verzeichnis wählen und den Server starten:

Go Fyne Webserver

Die Karte sollte dann unter localhost:8080 oder einem ähnlichen Port aufrufbar sein (einfach auf die Adresse im Fenster klicken).

Möglichkeit 2: QGis

Auch QGis ist in der Lage, Leaflet-basierte Karten zu erstellen. Das Vorgehen ist eigentlich relativ einfach, wenn man verstanden hat, wo die Fallstricke liegen. Knackpunkt ist hier das Koordinatensystem bzw. die Projektion.

Nachdem man QGis geöffnet hat, installieren wir zunächst den “Freehand raster georeferencer”. Das funktioniert über “Erweiterungen"⇒"Erweiterungen verwalten und installieren…” und die Suche nach dem georeferencer im Feld. Nach der Installation steht uns dann im Menü “Raster” diese Erweiterung zur Verfügung.

Auf einer neuen Karte erstellt man zunächst das OpenStreetMap Layer. Damit weiß man schon mal, wo die Welt ist:

QGis: OSM Layer

Jetzt öffnen wir das Menü “Raster"⇒"Freehand Raster Georeferencer"⇒"Add raster for interactive georeferencing”. In der Dateiauswahl suchen wir nun unser Bild. “Add new” fügt das Bild hinzu:

QGis: Mit Bild

Nun der eigentliche Trick: Wir müssen das Bild auf die Weltkarte projizieren. Dazu wählen wir “Scale” im Werkzeugmenü des Referenzers aus (gelbes Feld “SC”). Jetzt kann man das Bild, während man STRG und die linke Maustaste gedrückt hält, durch Verschieben der Maus vergrößern oder verkleinern. Wir wollen das Bild möglichst so groß haben wie die Weltkarte:

QGis: Bild auf Weltkarte

Damit ist das Bild von den Koordinaten her korrekt ausgerichtet. Die OSM-Karte blenden wir aus, die Transparenz des Bildes setzen wir auf 0 (Layer links unten, Rechtsklick “Eigenschaften…”).

Mit dem Menüpunkt “Verarbeitung"⇒"Werkzeugkiste” öffnen wir rechts die Werkzeugkiste und suchen nach “XYZ”. Der Punkt “XYZ-Kacheln erzeugen (Verzeichnis)” ist das, was wir wollen.

QGis: XYZ-Kacheln erzeugen

In dem Dialog wählen wir “Extent"⇒"Aus Layer berechnen"⇒unser Bildlayer. Minimum und Maximum Zoom sollte ähnlich wie mit gdal oben sein - in unserem Fall 0 bzw. 6. Unten ist es sinnvoll, ein Ausgabeverzeichnis und eine Ausgabedatei (Leaflet) zu wählen. Wenn man nun “Start” drückt, sollte die Karte korrekt erstellt werden. Diese ist auch Offline aufrufbar (ohne Server wie oben). Will man sie im Internet veröffentlichen, muss man allerdings noch etwas Hand anlegen.

QGis: XYZ-Kachel-Dialog

Fazit

Welche der beiden Methoden man verwendet, ist offen. Die erste Methode erfordert etwas technisches Verständnis, ist jedoch durch das Skripting einfach umsetzbar. Die zweite ist interaktiver, durch die Anpassung des Bildes an das Koordinatensystem ist die Umsetzung etwas fummeliger.

Durch die Einloggen bei den Kommentaren werden zwei Cookies gesetzt. Mehr Informationen im Impressum.
Follow me