000
21.11.2015, 00:40 Uhr
Yadgar
|
Hi(gh)!
Ich habe ein Programm geschrieben, das aus Bitmaps (TGA-Format) mit aus eingescannten topographischen Karten extrahierten Höhenlinien 16-bit-Heightfields für POV-Ray erzeugen soll. POV-Ray interpretiert dabei nur die Rot- und Grünwerte, so dass sich 65536 Höhenstufen ergeben.
Das Programm liest zuerst eine TGA-Datei (unkomprimiert, 24-bit, Beginn oben links) ein und errechnet für jedes Pixel mit einem Blauwert von 0 einen Farbindex aus den Rot- und Grünwerten (Rot * 256 + Grün). Alle Pixel mit einem Blauwert größer als 0 (also der z. B. weiße Hintergrund zwischen den Höhenlinien) werden mit -1 kodiert. Diese Daten werden in einem zweidimensionalen vector-Array vom Typ int gespeichert.
Parallel dazu wird ein gleichgroßes zweidimensionales Array vom Typ bool erzeugt und mit Werten gefüllt: true für im Original vorhandene Höhenlinien-Pixel, false für noch zu interpolierende Pixel.
Danach beginnt vom Koordinatenursprung der Bilddatei (also oben links) aus für jedes noch nicht interpolierte (also mit -1 kodierte) Pixel die Abtastung nach vorhandenen Höhenlinienpixeln in der Nachbarschaft. Dies geschieht in acht Richtungen, jeweils paarweise nach Nord und Süd, Ost und West, Nordost und Südwest, Südost und Nordwest. Für jedes Richtungspaar wird die Zahl der Iterationen bis zum erstmaligen Auftreten eines bereits gesetzten Pixels (also mit Blauwert = 0) festgehalten, soweit in jeweils beiden Richtungen unterschiedliche (!) Farbindexwerte gefunden werden, wird für jedes Richtungspaar ein nach den jeweiligen Entfernungen zum nächsten Original-Höhenlinienpixel gewichteter Mittelwert gebildet.
Bei den beiden diagonalen Richtungspaaren werden zusätzlich noch in jeweils rückwärtiger Abtastrichtung mit je einer Seite angrenzende Pixel berücksichtigt
Aufgrund der vier Richtungspaare können sich bis zu vier solcher MIttelwerte ergeben, die in einem dynamischen Array gespeichert werden und anschließend wiederum arithmetisch gemittelt werden. Dieser Mittelwert wird auf Ganzzahlen gerundet und in das vector-Array mit den Farbindexwerten geschrieben.
Nach Abschluss der Interpolation werden die Farbindexwerte in BGR-Tripel zurückgerechnet und eine TGA-Datei mit den neuen Bilddaten geschrieben, der Dateiname erhält den Anhang "_interpolated".
Soweit die Theorie. Tatsächlich gibt es gegenwärtig hauptsächlich zwei Probleme: geschlossene Höhenlinien, innerhalb derer zu interpolierende Pixel nur gleichwertige Höhenlinienpixel als Nachbarn haben (also Bergkuppen und Senken) und Pixel, die nahe am Bildrand liegen.
Letztere bleiben weiß, wohingegen Pixeln innerhalb geschlossener Höhenlinien teilweise Farbwerte zugewiesen werden, die (im Falle von Bergkuppen; Senken habe ich noch nicht getestet) niedriger sind als die umgebende Höhenlinie. Um dieses Problem zu vermeiden, habe ich das zusätzliche Array mit den bool-Werten zur Kennzeichnung ursprünglich vorhandener Höhenlinien-Pixel eingeführt. Abgesehen davon, dass sich selbst auf diese Weise immer noch Fehlpixel innerhalb geschlossener Höhenlinien einschleichen, treten jetzt auch digital verlaufende Artefakte auf, die vorher (also ohne bool-vector) nicht vorhanden waren.
Zur Veranschaulichung:
Test-Bitmap 10 x 10, original Test-Bitmap 10 x 10, interpoliert Test-Bitmap 157 x 115, original Test-Bitmap 157 x 115, interpoliert (mit rechter Maustaste anklicken und dann speichern - andernfalls wird möglicherweise ein Fehler angezeigt!)
Der Programmcode
Wahrscheinlich werde ich das bool-Array wieder zurücknehmen; allerdings stellt sich für mich auf jeden Fall die Frage, wie ich einen Algorithmus finde, der zuverlässig erkennt, ob sich ein Pixel innerhalb einer geschlossenen Höhenlinie befindet... könnt Ihr mir da weiterhelfen?
Bis bald im Khyberspace!
Yadgar -- Flagmaker - ein Programmier-Blog Dieser Post wurde am 21.11.2015 um 00:43 Uhr von Yadgar editiert. |