PNG-Optimierung extrem
Geschrieben von ThiemoHeute bin ich auf einen interessanten Beitrag im ZFX-Forum (dem offiziellen „Nachfolger“ von Developia) aufmerksam geworden. Der Autor Krishty versucht, die Kompression von PNG-Grafiken ins Extrem zu steigern, noch weiter als es mit den gängigen PNG-Optimierern pngcrush, OptiPNG oder dem von mir bevorzugten PNGOUT möglich ist.
Die genannten Werkzeuge stecken unheimlich viel Rechenaufwand in die Analyse einer PNG-Grafik und versuchen, ein globales Minimum für den komprimierten Datenstrom zu finden. Das Ergebnis kann trotzdem weiterhin mit jedem Webbrowser oder Bildbetrachter geöffnet werden.
Krishty wirft diese Zwänge über Bord und eröffnet sich damit zwei interessante Lösungsmöglichkeiten:
- Er analysiert die PNG-Grafik nur, findet den perfekten Vorfilter und speichert die PNG-Datei völlig ohne Kompression ab. Die Kompression überlässt er anschließend 7-Zip. Das lohnt sich vor allem bei vielen gleichartigen Grafiken. Diese werden nicht mehr einzeln betrachtet sondern 7-Zip hat die Möglichkeit, ein „solides“ Archiv über alle Dateien zu bilden.
- Er tauscht den Datenblock innerhalb der PNG-Dateien durch einen eigenen aus, der eine wesentlich aufwändigere Kompressionsmethode nutzt. Diese PNG-Dateien sind dann mit keinem anderen Programm mehr lesbar, nur innerhalb des Spiels, für das sie gemacht wurden.
Für Glow kommt nichts davon in Frage. Interessant ist es aber allemal.
Zum Vergleich fasse ich einmal meine wichtigsten Erkenntnisse zusammen, die ich während der Arbeit an unserem Spiel gewonnen habe. Daraus wollte ich schon lange einen eigenen, extralangen Artikel machen. Das ist er also.
- Ich benutze nur noch PNGOUT, keinen anderen Optimierer mehr. OptiPNG liefert auch ganz gute Ergebnisse, aber im Vergleich habe ich festgestellt, dass PNGOUT unsere 32-Bit-RGBA-Rendergrafiken meist effektiver eindampft. Deshalb spare ich mir den Aufwand, mehrere Tools durchlaufen zu lassen, jetzt ganz.
- Ich lassen PNGOUT immer mit mindestens zwei verschiedenen Filtern durchlaufen. Einmal mit der Automatik
/f5, bei der PNGOUT versucht, eine optimale Filtermethode für jede Bildzeile zu finden. Und einmal mit/f0, das heißt ganz ohne Vorfilter. Und eventuell noch einmal mit/f1, dem Filter, der immer das jeweils vorhergehende Pixel zum Vergleich heran zieht. Meist produziert/f5die besten Ergebnisse, aber bei manchen Bildern sind Durchläufe ohne Vorfilter noch ein paar Prozentpunkte besser. Die Filter 2, 3 und 4 lohnen sich meiner Erfahrung nach dagegen so gut wie nie. - Wir arbeiten sehr viel mit 32-bittigen Bildern, also mit 24 Bit Farbtiefe und einem 8 Bit Alphakanal. Dort, wo der Alphawert Null ist, ist von den 24 Farbbits nichts zu sehen. Dummerweise speichern manche Programme trotzdem etwas dort ab, obwohl man es überhaupt nicht sehen kann. Aufgefallen ist mir das einmal, als in einer linear interpolierten Grafik plötzlich weiße Pixel an den Rändern aufflackerten. PNGOUT lässt diese unsichtbaren Daten bewusst intakt. Meine Lösung: Ich habe mir ein kleines Tool geschrieben, dass eine PNG-Datei pixelweise durchgeht und überall dort, wo A=0 ist, auch R=0, G=0 und B=0 setzt. Das hat manche Grafiken, die ganz merkwürdigen Datenmüll in ihren transparenten Bereichen enthielten, noch einmal auf die Hälfte reduziert.
- Beim Lesen des ZFX-Beitrags fiel mir noch etwas ein: Man sollte Sprite-Animationen mit vielen gleichartigen Animationsphasen gemeinsam in einem großen PNG-Bild speichern, nicht einzeln, wie wir es bei Glow machen. Das hat mehrere Vorteile: Verringerte Zugriffszeiten auf die Festplatte, schnelleres Laden durch weniger Fragmentierung. Und der Kompressionsalgorithmus kann sein Wissen über die vorhergehende Animationsphase auf alle folgenden anwenden. Ein paar einfache Tests zeigen aber, dass diese eigentlich offensichtliche Idee in vielen Fällen erstaunlich wenig bringt. Teils werden lange Bildstreifen sogar ein paar Bytes größer als die einzelnen Dateien zusammen genommen. Bei sehr vielen, sehr kleinen Dateien kann das aber durchaus noch einmal 20 % einsparen. Wie man die Bilder anordnet (als horizontaler oder vertikaler Streifen oder als Rechteck), ist meinen schnellen Tests zufolge ziemlich gleichgültig.
25. Oktober 2011 um 23:18
Der Autor hat mich darauf hingewiesen, dass optimierte PNG-Dateien sogar schneller laden, das heißt, weniger CPU-belastend sind. Und noch eine Idee kam an die Oberfläche: OptiPNG soll besser darin sein, die optimalen Vorfilter für jede Bildzeile auszuwählen. Was, wenn man anschließend PNGOUT mit /f6 darüber laufen lässt? Dann behält es die Vorfilter-Auswahl von OptiPNG bei und komprimiert nur neu (darin ist PNGOUT zweifelsfrei besser). Ich probiere das gerade aus.
26. Oktober 2011 um 01:54
Zwischenergebnis mit ein paar Glow-Grafiken: Die Kombination OptiPNG + PNGOUT kann in seltenen Fällen wirklich effektiver als PNGOUT allein sein. Aber höchstens mal 1 Promille. Im Mittel bringt es gar nichts.
26. Oktober 2011 um 21:02
Ich muss mich korrigieren. Wenn man es richtig macht, kann die Kombination aus irgend einem anderen PNG-Optimierer + PNGOUT durchaus 1 bis 2 Prozent, manchmal sogar 5 Prozent einbringen, zusätzlich zu dem, was PNGOUT von sich aus schafft. Aber man muss auf die Reihenfolge und die richtigen Parameter achten:
Zuerst zwingen wir mit „optipng -force“ das andere Tool dazu, die Datei auf jeden Fall neu zu erzeugen, auch wenn sie dadurch größer wird. Die Kompression ist uns in diesem Schritt nämlich egal, uns geht es nur um die Vorfilter-Heuristik. Deswegen muss auch „optipng -o7″ nicht sein, „-o3″ oder sogar „-o1″ sollte völlig reichen. Danach lassen wir mit „pngout /f6″ nur die Kompression optimieren, die Vorfilter bleiben dabei unangetastet. Zum Schluss noch einmal „pngout /f5″ und wenn man mag auch noch „/f4″ bis hinunter zu „/f0″, und es sollte perfekt sein.
Kurz:
1. Kopien erstellen, damit wir eventuell schon optimale Dateien nicht verlieren, falls das Folgende nichts bringt.
2. optipng -o3 -force *.png
3. for %i in (*.png) do pngout /f6 %i
4. Die gleiche Schleife noch mehrmals mit /f5 bis /f0.
5. Mit den Kopien vergleichen.
23. November 2011 um 12:14
Hm, und lohnt sich die ganze Mühe? Man spart letztendlich, wenn alles sehr gut geht 5% der Downloadgröße, aber wen interessiert es heute noch, ob man 120MB oder 114MB runterladen muss?
Und in der Zeit, die man für das finden des Optimalen Verfahrens investiert hat, sind Festplatten pro MB wieder 5% billiger geworden.
Klar sind Optimierungen sinnvoll, aber ich finde das hier ist eher so ein Fall, wo das Prinzipielle Interesse an der Möglichkeit wichtiger ist, als der tatsächliche Nutzen, oder?
23. November 2011 um 20:38
Ja Jonathan, dem ist so. Wie etwa bei 64kb oder gar 4kb Intros. Ich persönlich sehe das aus der Sicht eines berühmten Werbeslogans: Entdecke die Möglichkeiten. ;)