Mir ist neulich aufgefallen, dass ich dieses Jahrzehnt noch nicht Dwarf Fortress gespielt habe. Überhaupt noch nicht. Und das Jahrzehnt ist schon wieder halb herum. Aber darum kümmere ich mich später, denn in diesem Zusammenhang ist mir ein altes Succession-Game eingefallen, das ich mit Arbeitskollegen gespielt habe, und dass es leider nur vier In-Game-Jahre geschafft hat, bevor uns die Spieler_innen ausgegangen sind. Dazu hat, dem Brauch eines Succession-Games, jeder einen Bericht geschrieben, was in dem entsprechenden Jahr in der Festung passiert ist (aus der Sicht eines Zwergs). Mit Screenshots.
Wer hier regelmäßig liest, weiß, dass ich eine Obsession für Bilddateigrößenoptimierung entwickelt habe. In diesem Post geht es nicht um Dwarf Fortress. Es geht um Bildgrößenkompression. Wer möchte, kann sich ja vorher noch meine kurze Einführung in verlustfreie und verlustbehaftete Kompression anschauen. Dort steht auch eine Faustformel, wann man welche Kompressionsvariante verwenden sollte.
Nun eignen sich Dwarf Fortress-Screenshots sehr gut für verlustfreie Kompression, zumindest mit der klassischen Grafik. Die ist nämlich nichts weiter als der ASCII-ähnliche (aber nicht kompatible) Zeichensatz CP437, eingefärbt in eine von 16 Farben, wobei der Hintergrund ebenfalls eine von 16 Farben haben kann, aber meisten grau ist. Die Darstellung der Zeichen hat keine Kantenglättung. Optimal für verlustfreie Kompression. Beispiel:

Oder, hereingezoomed, damit man die Pixel besser erkennen kann:

Lässt sich super komprimieren. Das obere Bild? 502×475 Pixel, nur 8,5 kiB groß als WebP. Insgesamt komme in einem Jahr auf 116 kiB an Bildern und in dem anderen Jahr auf 348 kiB. Der Kollege für Jahr zwei kommt auf 968 kiB, der Kollege für Jahr drei sogar auf 6,2 MiB. Und beide haben weniger Bilder als ich, in Jahr 4 habe ich sogar deutlich mehr Bilder. Wie kommt das?
Zum einen haben die Kollegen oft deutlich größere Bildausschnitte genommen. Das hätte man kleiner halten können, aber geschenkt. Der Kollege von Jahr 3 hat nicht die klassischen DF-Texturen genommen, sondern andere, mit mehr Details und Farben. Trotzdem noch relativ gut komprimierbar. Der Kollege von Jahr 2 hat aber die Standardtexturen. Allerdings hat er nicht aufgepasst und alle Screenshots als JPEG abgespeichert. Autsch.
Nun hängt diese Story momentan noch bei Github herum. Ich hatte mir überlegt, die mal auf meinen eigenen Server zu packen, als Teil meines digitalen Gartens. Aber dann muss ich irgendwas mit diesen übergroßen Screenshots machen. Und darum geht es in diesem Blogpost.
Bestandsaufnahme und Kompression in verschiedenen Formaten an einem Beispielbild
Als Basis für die Analyse nehme ich einen Screenshot eines fliehenden Kobolds. Der hat gewissen Ähnlichkkeit mit dem Screenshot oben, weil er auch draußen aufgenommen wurde. Die Auflösung ist ein bisschen kleiner (454×362), aber die Dateigröße als JPEG sind enorme 168 kiB. Ich werde hier erst einmal immer nur einen kleinen Ausschnitt des Bildes wiedergeben, dafür aber hereingezoomt, damit man sehen kann, was mit den einzelnen Pixeln passiert. Zunächst einmal habe ich verschiedene Bildformate mit verschiedenen Einstellungen ausprobiert:






Von oben nach unten:
- Das Originalbild. In der Originalvariante (JPEG) 168 kiB groß, als verlustfreies WebP nur 126 kiB. Die Kompressionsartefakte machen verlustfreie Kompression deutlich schwieriger. Als verlustfreies AVIF übrigens 212 kiB groß. Ich habe noch keinen echten Anwendungsfall für verlustfreie AVIF-Dateien gefunden.
- Verlustfreies WebP mit maximaler Qualität (100). Deutlich erkennbar: Die veränderten Rottöne. 81 kiB groß.
- Verlustfreies WebP mit 75 % Qualität (Standardeinstellung von
cwebp). Auch hier stark veränderte Rottöne. 33 kiB groß. - Verlustfreies Avif mit 50 % Qualität. Bild deutlich besser wiedergegeben als irgendein Webp. 25 kiB groß.
- WebP mit der
cwebp-Option-near-lossless 0. Diese Option macht ein verlustbehaftetes Farb-Preprocessing und wendet danach verlustfreie Kompression an. 0 bedeutet maximales Preprocessing. 57 kiB groß. - WebP mit
-near-lossless 60, dem empfohlenen Wert. Kaum ein Unterschied zum Original erkennbar, 84 kiB groß.
Da die Bilder eh verlustbehaftet sind, hätte ich mich hier mit der Avif-Variante zufrieden geben und Schluss machen können. Was aber, wenn wir die Verluste irgendwie wieder rückgängig machen können?
Recovery von der verlustbehafteten Kompression
Nun, eigentlich kann man die Informationen, die beim Komprimieren verloren gehen, nicht zurückholen. Das ist Informationstheoretisch nicht möglich. Wir haben hier aber einen großen Vorteil: Wir haben Kontextwissen. Wir wissen, dass die Screenshots Zeichen im Raster zeigen. Wir wissen, dass sie nur eine begrenzte Farbpalette zu Verfügung hatten. Wir kennen alle möglichen Zeichen. Wir könnten die Bilder vermutlich also wirklich so wiederhestellen, wie sie waren (von ein paar Pixeln am Bildrand abgesehen, die sich vielleicht nicht mehr konkret einem Zeichen zuordnen lassen).
Aber das wäre mir dann doch zu viel Arbeit. Aber zumindest die Farbpalette zu reduzieren wäre schon cool. Deswegen habe ich aus verlustfreien DF-Screenshots die Farbpalette extrahiert:
![]()
Es gibt ein schönes Tutorial, wie man mit Imagemagick die Farben auf eine Palette reduziert. Ich habe mich, wie gesagt, auf eine vorgegebene Palette festgelegt, also habe ich folgenden Befehl genutzt:
magick 1-koboldThief.jpg +dither -remap palette.png 1-koboldThief_16_colors_remap.png
+dither deaktiviert hier Dithering, sonst hätte Imagemagick mir vermutlich noch ein paar falsche Pixel mehr reingedrückt. Das Ergebnis sieht so aus:

Perfekt ist es noch nicht. Gerade die helleren Zeichen haben immernoch einen Farbverlauf, weil es dunklere Farben gab, um den Verlauf darzustellen. Manche Pixel sind völlig falsch. Aber das Gesamtbild ist gut, und die Dateigröße kann sich sehen lassen: Sie ist von 168 kiB auf 7,8 kiB geschrumpft. Damit steht dem Ziel, den Bericht, in dem die Screenshots verwendet werden, auf meinem eigenen Server zu hosten, nichts mehr im Weg. Naja, außer einer Menge Arbeit. Aber der schwierige (andere sagen auch: der interessante) Teil ist geschafft.
Hier zum Abschluss noch einmal der „wiederhergestellte“ Screenshot:






