PNG mit 7-Zip

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

PNG mit 7-Zip

Beitrag von Krishty »

Hi,

Ich hörte, dass für die Kompression der Daten einer PNG-Datei auch andere Bibliotheken als zlib eingesetzt werden könnten, insbesodere 7-Zip.

Gibt es Informationen, wieviel höher 7-Zip diese Dateien komprimieren kann und wie 7-Zip in libpng eingebunden wird? Ich würde diese Möglichkeit gerne in meinem Projekt nutzen.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 5047
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Schrompf »

Ich weiß nicht, wieviel Dir das bringt - der allgemeine Vergleich zip zu 7zip stellt Gewinne im Bereich von 10 bis 20% in Aussicht. Aber ich fände die Frage viel spannender, welches Programm Deine PNGs dann noch lesen können soll?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Lesen ist kein Problem, ich verwende die PNGs nur für Cache-Dateien innerhalb meines Programms (also auch nicht als eigenständige Dateien, sondern mit anderen zusammengeschrieben). Da die leicht in die hundert MiB gehen, ist jedes Prozent willkommen (10 bis 20% sind sehr verlockend, es sollen bei manchen Daten bis zu 40% sein, aber bei PNGs bin ich skeptisch) … und 7-Zip soll ja auch effizienter mit aktueller Hardware umgehen können (schneller vergleichbare Kompression erreichen) …

… denke ich zumindest – darum frage ich, ob schon jemand Erfahrungen damit gemacht hat … nicht, dass ich es mühsam implementiere und es sich als Trugschluss herausstellt.

Achja, nervig sind an zlib auch die 250 Warnungen, die mir bei jeder Kompilierung ausgespuckt werden … bei jedem Rebuild verpesten die mir die Logdatei :roll: … von Hand abstellen suckt …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Hey, ich grabe das alte Thema mal wieder aus. Ich habe wieder ein bisschen mit PNGs experimentieren können und kriege sie bei der Archivierung mit 7-Zip (anstelle der PNG-eigenen Deflate-Kompression) nochmal 5 bis 20 % kleiner als durch eine Optimierung mit OptiPNG und PNGOut … damit liegen sie nun 10 bis 35 % unter Serien-PNGs. (Kracher ist eine Oberflächenkarte des Mondes, die auf 53% der Originalgröße schrumpft.) Übrigens ist LZMA dabei nicht die effektivste Kompression – in vier von fünf Fällen liegt PPMd vorn, und zwar nochmal mit dem gleichen Abstand, den LZMA zu Deflate hat.

Ich wollte mal fragen, was gerade State-of-the-Art bei der verlustfreien Bildkompression ist? Um z.B. größere Screenshot-Sammlungen zu archivieren … gibt es da ein paar brandneue, heiße Containerformate und Kompressionsalgorithmen um die Daten noch mehr zu quetschen, oder ist die Entwicklung bei PNG stehen geblieben? Wie sieht das mit der Lossless-Form von JPEG2000 aus? Ich höre immer nur aus zweiter Hand davon, eine Implementierung in freier Wildbahn habe ich nie gesehen …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Okay, mal ein paar Benchmarks:
  1. PNG, mit Gimp auf höchster Kompressionsstufe gespeichert (so dürften die meisten PNGs vorliegen).
  2. PNG, optimiert durch OptiPNG und PNGOut (so ziemlich die Grenze des Standard-PNG-Formats).
  3. Optimiertes 7-Zip-Archiv mit einem für die Archivierung optimierten PNG.
  4. Optimiertes 7-Zip-Archiv mit einer gewöhnlichen BMP.
A: „ZFX“, ein Screenshot der ZFX-Hauptseite in 1280 × 964.
  1. 140 656 B
  2. 93 092 B (66,18 %)
  3. 65 920 B (46,87 %)
  4. 61 574 B (43,78 %)
Hier schneidet die BMP besser ab als das PNG … obwohl bei der Archivierung erkannt wurde, dass das Bild ohne Filter am besten komprimiert werden kann (die Bilddaten des PNGs und der BMP also bitweise identisch sein müssten). Hier muss ich nachforschen, was schief gegangen ist …


B: „Crysis“, dieser Screenshot von Crysis in 1920 × 1200. Ist für mich von Interesse, weil ich vor allem Screenshots archiviere. Er ist kontraststark und detailliert, sein Hintergrund vergrieselt – das sollte PNG also nicht in die Hände spielen.
  1. 3 968 817 B
  2. 3 918 538 B (98,73 %)
  3. 3 363 884 B (84,76 %)
  4. 3 592 605 B (90,52 %)
Hier funktioniert PNG wieder wunderbar. Die Kompressionsmethode ist übrigens (sowohl beim PNG als auch bei der BMP) PPMd:o32:mem29; mit LZMA fiele das Ergebnis rund fünf Prozent schlechter aus.


C: „Moon“, eine Cubemap-Textur der Mondoberfläche in 4096 × 3072, eine kleine Version ist im Anhang. Sehr hoch detailliert und unregelmäßig, aber dennoch in einem gleichmäßigen Farbton (also nicht bloß grauer Matsch) … einigermaßen repräsentativ für Texturdaten und damit interessant zu benchen.
  1. 9 396 374 B
  2. 7 810 136 B (83,12 %)
  3. 4 980 483 B (53,00 %)
  4. 4 960 685 B (52,79 %)
Hier werden Standard-PNGs total abgehängt. Wieder wird die beste Kompression mit PPMd:o32:mem29 erreicht (mit LZMA fiele sie 13 % schlechter aus), eine rohe Bitmap liegt 20 KiB vorn. Hier das gleiche Problem wie beim ZFX-Screenshot: Bei der Archivierung wurde eine ungefilterte Datei erzeugt, trotzdem lässt sie sich nicht so gut komprimieren wie eine ansonsten gleichwertige BMP. Dem muss ich unbedingt auf den Grund gehen.


D: „Tokyo“, dieses Foto in 1600 × 1200. Ich wollte einfach mal gucken, wie gut sich PNG bei Fotos macht (für die es ja überhaupt nicht ausgelegt ist). Die Quelldatei ist ein JPG und vermurkst mit ihren Artefakten die Kompression zusätzlich, hochauflösende Fotografien in verlustfreien Formaten habe ich aber nicht gefunden :(
  1. 2 988 420 B
  2. 2 933 840 B (98,17 %)
  3. 2 387 056 B (79,88 %)
  4. 3 665 980 B (122,67 %)
Warum 7-Zip hier mit der BMP so versagt (und sich außerdem für LZMA:6m entscheidet), kann ich nicht sagen. Dafür liegt ein für die Archivierung (wieder mit PPMd:o32:mem29) optimiertes PNG ausnahmsweise mit Abstand ganz vorn.


Fazit: Für die langfristige Archivierung ist PNG nicht optimal, aber mit der richtigen Kompressionsmethode lässt sich das ändern (und die Dateigröße teils halbieren). Ich werde weiter feilen und prüfen, warum ungefilterte PNGs so schlecht abschneiden.

Noch ein Wort zu Effizienz (hier wurde ja nur die Effektivität behandelt): Das Vorbereiten eines PNGs auf die Kompression, die Kompression mit 7-Zip und die Optimierung mit Ultra7z geht rund vier Mal so schnell wie die Optimierung eines PNGs durch OptiPNG und PNGOut im Perfektionisten-Modus.

Mich interessiert, wie JPEG / JPEG 2000 wohl im Lossless-Modus abschneidet. Es soll ja ein paar Prozent vor PNG liegen … die Frage ist, ob es auch noch vor durch 7-Zip komprimierten PNGs läge?

Edit: Klar, dass eine Bitmap anders komprimiert als ein ungefiltertes PNG – in der Bitmap liegen die Pixel als BGR-Tripel vor (RGB in PNG) und sind außerdem von unten nach oben geschrieben (in PNG von oben nach unten). Darauf habe ich leider keinen Einfluss … ob sich vertikal gespiegelte, Komponenten-vertauschte Daten statistisch gesehen besser komprimieren lassen ist aber auch eine gute Frage ;)
Dateianhänge
Tex.png
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Mal ein kleines, aber feines Update: Das Weglassen der Kompression hat libpng offenbar zu unnötigen Redundanzen innerhalb der Dateien veranlasst – Chunks kamen vielfach vor, obwohl sie nicht sollten. Ich habe DeflOpt benutzt, um sie zu beseitigen, und nun komprimiert ein auf die Archivierung vorbereitetes PNG in jedem Fall besser als eine BMP. Jetzt muss ich nur zusehen, dass ich die Ursache des Überschusses finden und beseitigen kann, damit ich nicht mehr auf DeflOpt angewiesen bin … im Hex-Editor ist das aber ziemlich mühsam :(

Edit: Okay, mit TweakPNG ist das tausend Mal angenehmer.

Edit 2: Jetzt ist alles klar. Die Größe des IDAT-Chunks wird durch den Wert für ::png_set_compression_buffer_size() bestimmt; sind die Bilddaten größer, wird das Bild auf weitere IDATs aufgeteilt. Irgendwo muss ich irrtümlicherweise gelesen haben, dieser Wert dürfe 8192 nicht überschreiten :?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Ich habe mit Dmitri Shkarins PPMd-Implementierung rumgespielt (so gut der Kompressor auch ist, so fürchterlich ist sein Quellcode …) und das Maximum der Kompression je nach Bildtyp bei 85 bis 40 % der Serien-PNG-Größe festgemacht (85 werden selbst im schlechtesten Fall erreicht, weniger als 40 konnte ich nie beobachten). Von hier aus lassen sich nur noch einzelne Bytes rausholen, indem man z.B. nur den IDAT-Chunk komprimiert statt der gesamten Datei (was mir aber momentan zuviel Frickelei an libpng wäre).

Jetzt liegt mein Hauptaugenmerk erst einmal darauf, das Finden der optimalen PPMd-Parameter zu beschleunigen … Brute-Force dauert das einfach zu lang … (obwohl der Kompressionsunterschied zwischen optimalen und katastrophalen Parametern unter 5 % bleibt).
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Soooo, fast fertig:

Ich habe nun ein kleines Tool geschrieben, das die Bilddaten aus PNGs extrahiert und statt Deflate mit PPMd zurück schreibt (und auch den umgekehrten Weg beherrscht). Als compression method im IHDR-Header benutze ich dabei 80, also den ASCII-Code für P. Dass nun nur noch pure Bilddaten komprimiert werden, spart zwischen 500 B und 6 KiB (weil keine Metadaten mehr die Kompression verschmutzen).

Die endgültigen Ergebnisse für die Benchmarks sind 42,74 % (ZFX) / 83,35 % (Crysis) / 49,9 % (Moon) / 79,14 % (Tokyo) der Serien-PNG-Größe.
Gegenüber PNGs, die mit OptiPNG, PNGOut und DeflOpt optimiert wurden, sind das 67,18 % (ZFX) / 84,43 % (Crysis) / 60,07 % (Moon) / 80,61 % (Tokyo) – bei leicht kürzerer Laufzeit, wie man anmerken sollte.

Interessant ist, dass Windows mit PNGs unbekannter Kompression ziemlich gut umgehen kann. Da die Metadaten korrekt sind, werden Thumbnails korrekter Größe erzeugt, die dann einfach komplett schwarz sind. Auch Paint öffnet solche PNGs mit korrekten Ausmaßen und Farbtiefe, nur eben schwarz. Probleme wie einen abstürzenden Explorer (wie bei beschädigten IDAT-Chunks) gibt es nicht.

Das geschickte Wählen der PPMd-Parameter habe ich nicht eingebaut (langweilig). Brute-Force ist es zwar saulahm, aber immernoch schneller als PNGOut, also im vertretbaren Rahmen.

Der optimale Speicherverbrauch von PPMd liegt übrigens bei rund 10 MiB – ich habe 1 MiB als Minimum und 32 MiB als Maximum definiert, weil das beste Memory-Level aller Bilder in diesem Intervall lag.

––––––––––––––––

Wirklich zu interessieren scheint das Thema ja niemanden … ich lasse den Thread einfach mal hier liegen, in der Hoffnung, dass meine Ergebnisse irgendwann jemandem nützlich sind :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Jörg »

Wie teuer wird es denn mit PPMd, wenn man 2D-Unterbereiche aus einem Bild extrahieren will? Worauf ich hinaus will sind hierarchische Kompressionsverfahren...oder spielen die fuer dich keine Rolle?
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Ich habe ehrlich gesagt keine Ahnung, wovon du sprichst :) Was ist hierarchische Kompression?

2D-Unterbereiche lassen sich aus PNG sowieso schwer bis garnicht extrahieren – durch die Kompression weißt du nicht, wo die Bilddaten anfangen, durch die Vorfilter musst du auch vorausgehende Zeilen extrahieren und durch Interlacing können bestimmte Pixel quasi überall im extrahierten Stream liegen.

Edit: Okay, genau ein brauchbares Google-Ergebnis später denke ich, dass du auf Interlacing hinaus willst(?) … theoretisch braucht man bei PPMd nur wahlfreien Zugriff auf den aktuellen Kontext, der relativ klein ist. Es bliebe also mehr oder minder streamable … ich kann aber nichts Genaues sagen, weil ich die PPMd-Implentation einfach noch nicht vollständig verstanden habe :/
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 597
Registriert: 05.07.2003, 11:17

Re: PNG mit 7-Zip

Beitrag von Lord Delvin »

Sah ganz interessant zu verfolgen aus, warum schlägst du keinen patch für libpng vor, der dein Ergebnis verwendet? Dann hätte jeder was davon.
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Jörg »

Nein, eher in Richtung Mipmap-Pyramiden. In Bildern hast Du ja hauptsaechlich lokale, 2-dimensionale Aehnlichkeiten / Redundanzen, die man gut ausnutzen kann. Eventuell bringt schon ein Umsortieren der Pixel (mit einer der vielen Space-Filling Curves) einen Bonus. Kombiniert man das mit einem Quad-Tree, dann sollte das effiziente Entpacken von 2D-Unterbereichen leichter werden. Kann man ja manchmal brauchen (Mega-Textures).
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Huch, Interesse *erschreck* :)
Lord Delvin hat geschrieben:Sah ganz interessant zu verfolgen aus, warum schlägst du keinen patch für libpng vor, der dein Ergebnis verwendet? Dann hätte jeder was davon.
Wenn ihr was davon haben wollt, kann ich auch einfach meinen PNG-Repacker online stellen – der macht PNGs zwar größer, dafür lassen sie sich aber mit 7-Zip besser komprimieren als vorher. Wenn man für Bildersammlungen oder Installer eh archiviert, ist das die weitaus schnellere und einfachere Methode, noch mehr zu pressen (auch, wenn man dann eben fünf bis zehn Prozent hinter „echten“ PPMd-PNGs herhinkt), weil die PNGs standardkonform bleiben.

So lange ich nicht alle Bilder im Schnitt auf halbe Größe gequetscht kriege, wäre eine libpng-Extension imho zu viel Aufwand mit zu wenig Nutzen.


@Jörg: Okay, jetzt stoßen wir zu des Pudels Kern vor:

Was Mip-Map-Pyramiden und Megatextures angeht: Ich entwickle das ganz ohne Hintergedanken an Game-Development o.ä. … einfach, um meine Bilder kompakter archivieren zu können … der Nutzwert ginge also gegen Null. (Kann aber (mal wieder) sein, dass du mir zwei oder drei Schritte voraus bist :) )

Zur besseren Kompression durch 2D-Ähnlichkeiten: PNG reduziert das 2D-Bild schon relativ effektiv in einen 1D-Stream, indem es beim Speichern jeder Bildzeile auf die Vorherige zurückgreifen kann, bevor die Zeilen-Deltas dann durch die Kompression gejagt werden. Die Pixel umzusortieren könnte da zwar noch Verbesserungen bringen – dann müsste ich aber nicht mehr nur an der Kompressionsmethode rumwerkeln, sondern auch am Schreiben des Bildes selbst …

… da erhoffe ich mir gerade von einer anderen Methode mehr: Ich könnte bei PPMd 2D-Kontexts einsetzen, die auf die Zeilenbreite abgestimmt sind. Dann müssten sich 2D-Muster direkt mit PPMd erkennen lassen … habe gehört, damit könne man die Dateigröße erneut um ein Drittel reduzieren. Dann wäre ich endlich im Bereich der halben Größe der Serien-PNGs – und bräuchte nicht an den Annalen von libpng herumschrauben.

Ich bin gerade wirklich motiviert, das anzupacken, aber mathematisch unbegabt und des Russischen nicht mächtig im PPMd-Code rumzuwerkeln wird sicher frustrierend :)

Achja, ich habe übrigens auch schon einmal damit rumgespielt, Farbinformation von Helligkeit zu trennen und seperat zu komprimieren … war aber für den Popo.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Soooo, da ich in nächster Zeit keine Zeit habe, weiter auf dem Gebiet zu arbeiten, schmeiße ich zwei meiner Tools mal unter die Menge. Beide sind nur mit RGB- und Graustufen-PNGs getestet, mit VS 2010 kompiliert und noch nie auf einem anderen PC ausgeführt worden, Benutzung also nur auf eigene Gefahr.
PNG-Tools.zip
(134.79 KiB) 655-mal heruntergeladen
ArchiPNG: Bereitet PNGs auf effizientere Archivierung vor, wenn man eine oder mehrere Dateien übergibt (bzw auf die Exe zieht).

Das Resultat ist etwa so groß wie das Bild als unkomprimierte Bitmap, also wahrscheinlich größer als vorher … komprimiert man diese Datei dann mit einem File-Archiver, sollte das Resultat aber kleiner sein als ein sonstwie optimiertes PNG oder das gleiche Bild als sonstwie komprimierte Bitmap. Das kann nützlich sein, wenn man Bilder verlustfrei archivieren möchte, in Installer packt usw.

Alle möglichen Filtermethoden werden Brute-Force getestet und diejenigen ausgewählt, mit der sich die Datei optimal komprimieren lässt. Die Originaldatei wird dann mit dieser Filtermethode und ohne Kompression überschrieben. Um die Datei dann zu archivieren, empfehle ich 7-Zip – entweder, indem man dort manuell PPMd als Kompressionsmethode auswählt (nervig) oder, indem man einfach drauflos komprimiert und das Ergebnis danach mit Ultra7z optimiert (bequem). Mit anderen Kompressionsmethoden als PPMd wird das Ergebnis nicht optimal sein.


PPNg: Komprimiert PNGs (präziser: ihre IDAT-Chunks) mit PPMd statt dem standardmäßigen Deflate (und macht beim erneuten Aufruf diese Kompression wieder rückgängig). Beim Packen teuflisch langsam wegen Brute-Force (256 Versuche), aber auch nur als Spielerei gedacht. Die Optimierung auf zehn Versuche ist möglich, aber die zu implementieren war mir zu langweilig.

Die entstehenden PNGs (werden mit „.copy.png“-Postfix gespeichert) sind nicht mehr standardkonform und lassen sich von keinem anderen Programm mehr anzeigen (wohl aber lesen). Sie sind dann – sofern zuvor mit ArchiPNG optimiert – aber auch das Maximum, was man aus „gewöhnlichem“ PPMd rausholen kann. Entpackt man ein so komprimiertes PNG, wird es mit mittlerer Deflate-Kompression gespeichert, die Datei ist also vom Inhalt her identisch mit dem Original, aber nicht mehr vom Bitmuster und der Größe.


Die Kompressionsraten schwanken natürlich stark. Generell gilt: Je größer das Bild, desto größer die relative Ersparnis. Gescannte Kritzeleien in 2500×4000 bekomme ich z.B. von 19 auf 11 MiB, in 250×400 aber nurnoch von 350 auf 270 KiB.

Screenshot der ZFX-Hauptseite, mit GIMP auf höchster Kompression gespeichert:
140.656 B (100 %)
Nach ArchiPNG:
3.703.425 B (2633 %)
Nach ArchiPNG & PPNg:
60.112 B (42,74 %)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

libpng wählt den besten Zeilenfilter auf Basis des geringsten Durchschnitts der Zeilendeltas. Ich habe nun probiert, diese Entscheidung basierend darauf zu treffen, welches Resultat sich am besten komprimieren lässt (diese Methode ist auch im Quelltext schon vorgeschlagen, aber nicht umgesetzt).

Der Gewinn liegt dabei scheinbar nur bei etwa einem Prozent … ziemlich luschig – aber da ich nun eine rationale Entscheidung statt Brute-Force-Raten habe, bekomme ich die 20-fache Schnelligkeit gratis dazu. Als nächstes werde ich die Entscheidung auf Basis aller bisher komprimierten Zeilen treffen und schauen, ob sich ein besseres Resultat ergibt.

(Alles bezieht sich auf PPMd – wie viel besser diese Entscheidungsmethode bei der gewöhnlichen PNG-Kompression durch LZ77 ist, habe ich nicht gemessen.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: PNG mit 7-Zip

Beitrag von eXile »

Dürfte ich fragen, welche PNG-Chunks überhaupt für deine Programme von Interesse sind? Oder andersherum: Was löschst du häufig für Chunks raus?
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Garkeine. Ich optimiere lediglich den IDAT-Chunk, bzw. merge alle IDATs zusammen, falls es mehrere gibt. Wie sie sich mit privaten, also nicht standardisierten Chunks verhalten, kann ich aus dem Stehgreif nicht sagen – aber theoretisch müssten sie die übernehmen.

Die Programme in dem hochgeladenen Paket sind btw ein wenig alt; ich weiß garnicht, ob sie noch laufen (CRT von VS2010-RC und so).

Und ein Rückschlag: Auf einigen Bildern habe ich 11 % größere Ergebnisse als vorher. Also zurück ans Reißbrett.

Sooo. Die Auswahl danach, welcher Filter sich mit allen vorherigen Zeilen zusammen optimal komprimieren lässt, liefert gleiche Ergebnisse wie vorher. Immernoch suboptimal. Wahrscheinlich wird hier die Schere zwischen meiner PPMd-simulierenden Deflate-Kompression und echtem PPMd zu groß – das echte PPMd kann ich nicht benutzen, weil sich damit nur volle Kompressionen durchführen lassen; mittendrin zurückspringen und neu komprimieren (wie bei Deflate) geht aufgrund der Implementierung nicht.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Ich habe momentan mit etwas größeren Datenmengen zu tun, darum musste ich Anpassungen an ArchiPNG vornehmen: Es gibt nun eine 64-Bit-Version und die Optimierung wird garnicht erst begonnen, falls nicht genügend Adressraum zur Verfügung steht. (Weil ich aber Fragmentierung nicht voraussagen kann, kann es noch immer Abbrüche geben.) Außerdem werden aktuelle Versionen von zlib und libpng genutzt.

Getestet mit 38.400×28.800 Pixeln, 8 Bits pro Pixel (größer ging nicht, da GIMP dann abstürzt) auf einem Core i7 860:
GIMP:. . . . . . . . . 52,1 MiB
OptiPNG*:. . . . . . . 30,3 MiB / 230 min
ArchiPNG:. . . . . . 1044,5 MiB / 124 min
ArchiPNG + 7-Zip:. . . 22,1 MiB / 124 + 4 min **
ArchiPNG + Ultra7z:. . 15,1 MiB / 124 + 159 min ***

* höchste Stufe; manuell das /LARGEADDRESSAWARE-Flag nachgetragen
** PPMd Ultra
*** höchste Stufe; Ergebnis: PPMd:o24:mem29


Die Daten sind noch relativ synthetisch; sobald ich ein richtig fieses reales Szenario abgeschlossen habe, trage ich die Ergebnisse nach. Ich erwarte da weniger krasse Unterschiede.

Irgendwann sattle ich auch mal auf Multi-Threading um … weiterhin wäre es möglich, einen Bruchteil der Daten Ultra7z zu übergeben, damit nur 10 MiB Bruto-Force komprimiert werden müssen um die optimale Methode für das komplette GiB zu finden. Dann kommt man so langsam in Bereiche, in denen es sich lohnt. (Nach dem Motto: eine 100-MiB-Grenze weniger überschritten – eine Stunde weniger Wartezeit bei einem Filehoster.)
ArchiPNG.7z
(156.24 KiB) 445-mal heruntergeladen
Zum Entpacken wird 7-Zip 9.2, zum Ausführen die Visual C++ 2010 SP1-Laufzeitbibliothek benötigt. Benutzung wie immer – Drag'n'Drop und Kommandozeile für PNGs und Verzeichnisse.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Mr. Heat
Beiträge: 22
Registriert: 24.06.2008, 16:07
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Mr. Heat »

Ich bin leider erst jetzt über diesen interessanten Beitrag gestolpert. Ich habe ein paar Ergänzungen, die ich in einem Blogbeitrag zusammen gefasst habe: www.black-chronos.com/glow/2011/10/png- ... ng-extrem/

Hier meine Gedanken in Kürze:
  • Ich habe mir ein Tool geschrieben, dass den Alphakanal in PNG-Dateien säubert. Dort, wo A=0 ist, wird auch R=0, G=0 und B=0 gesetzt. Das macht nicht jedes Programm von Haus aus. Manche hinterlassen in den transparenten Bereichen regelrechten Datenmüll, der die Datei unnötig aufbläht. Die bekannten PNG-Optimierer säubern diese Bereiche bewusst nicht, da dadurch gewissermaßen (man könnte wohl darüber diskutieren) der Dateiinhalt verfälscht werden würde.
  • Einen ähnlichen Effekt wie mit deinem ArchiPNG kann man auch erreichen, indem man per Bildbearbeitung viele Einzelbilder in wenigen großen PNG-Bildern zusammen fasst. Das lohnt sich vor allem bei Sprite-Animationen mit sehr vielen kleinen Animationsphasen. Die Einsparung ist natürlich geringer als bei deinen Methoden, es hat aber den Vorteil, dass es die ganze Zeit über "normale" PNG-Dateien bleiben.
  • Es lohnt sich, PNGOUT mehrmals mit den Parametern /f0 bis /f5 durchlaufen zu lassen. Meiner Erfahrung nach ist das beinahe immer besser als OptiPNG.
Tiles

Re: PNG mit 7-Zip

Beitrag von Tiles »

Ich habe mir ein Tool geschrieben, dass den Alphakanal in PNG-Dateien säubert. Dort, wo A=0 ist, wird auch R=0, G=0 und B=0 gesetzt. Das macht nicht jedes Programm von Haus aus. Manche hinterlassen in den transparenten Bereichen regelrechten Datenmüll, der die Datei unnötig aufbläht. Die bekannten PNG-Optimierer säubern diese Bereiche bewusst nicht, da dadurch gewissermaßen (man könnte wohl darüber diskutieren) der Dateiinhalt verfälscht werden würde.
Es kommt auf den Verwendungszweck an ob die Farbpixel in den transparenten Breichen "Datenmüll" sind oder nicht. Nehmen wir zum Beispiel eine transparente Blatt-Textur für einen Low Poly Baum. Die wird in der Regel mittels Mipmapping kleinerskaliert je weiter weg der Kamerad ist. Und dabei bluten dann diese vorher im transparenten liegenden Pixel in den sichtbaren Bereich rein. Die Pixel werden ja beim kleinerskalieren zusammengemischt. Wenn du im transparenten Bereich nun alles schwarz machst hast du spätestens beim dritten oder vierten Mipmap Bild auch im sichtbaren Bereich alles schwarz. Ich sorge deswegen inzwischen dafür dass die sichtbaren Pixel in den unsichtbaren Bereich fortgeführt werden. Sprich wo es im sichtbaren Bereich grün ist ist auch mein transparenter Bereich im Umfeld davon unter der Haube grün. Natürlich ist meine Textur dadurch etwas grösser. Aber es ist ja für einen guten Zweck :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Tiles hat geschrieben:Nehmen wir zum Beispiel eine transparente Blatt-Textur für einen Low Poly Baum. Die wird in der Regel mittels Mipmapping kleinerskaliert je weiter weg der Kamerad ist. Und dabei bluten dann diese vorher im transparenten liegenden Pixel in den sichtbaren Bereich rein. Die Pixel werden ja beim kleinerskalieren zusammengemischt. Wenn du im transparenten Bereich nun alles schwarz machst hast du spätestens beim dritten oder vierten Mipmap Bild auch im sichtbaren Bereich alles schwarz. Ich sorge deswegen inzwischen dafür dass die sichtbaren Pixel in den unsichtbaren Bereich fortgeführt werden. Sprich wo es im sichtbaren Bereich grün ist ist auch mein transparenter Bereich im Umfeld davon unter der Haube grün. Natürlich ist meine Textur dadurch etwas grösser. Aber es ist ja für einen guten Zweck :)
Selber schuld. Dafür gibt es Premultiplied Alpha … ;)

Dieser Punkt hängt sich an der Definition von „verlustfrei“ auf: Für Archivierungsprogramme à 7-Zip bedeutet (imho) verlustfrei, dass die Bilder Bit für Bit identisch mit der Eingabe sind. Für PNG-Optimierer bedeutet verlustfrei, dass die Bild- und Metainformationen erhalten bleiben, obwohl sich die Repräsentation des Containers ändern darf (und sogar soll, wir wollen ihn schließlich kleiner haben).

Ich zähle den Alphakanal durchaus zu den Bildinformationen. Die Entscheidung, ob ein voll transparenter Pixel keinen Farbwert hat oder doch, setzt eine Interpretation voraus, die über die Kompetenzen des Containers hinausgeht: Ein PNG-Optimierer kann und darf sich nicht anmaßen, zu urteilen, wofür das Bild später verwendet wird. Falls das Tool hingegen genau auf deinen Verwendungszweck zugeschnitten ist (und dadurch über ausreichendes Wissen über deine Interpretation verfügt), kannst du das natürlich als verlustfrei durchgehen lassen, da diese Bildinformation für deinen Zweck nicht mehr relevant ist.

Die Entfernung der Farbwerte von transparenten Pixel fällt für mich also nicht mehr unter Verlustfreiheit generischer PNG-Optimierung. Wenn man mal so weit ist öffnen sich zwar ganz andere Tore (z.B. das Quantisieren von Echtfarb-PNGs auf optimale Paletten, wie es PNGQuant tut); allerdings sind dann alle Kompressionsergebnisse auf einen Schlag degradiert: Da man nun in einer Liga mit anderen verlustbehafteten Kompressionsmethoden wie JPG oder Wavelet-Kodierern spielt, muss man auch ähnliche Kompressionsraten erbringen … und das bedeutet ein bis drei Bits pro Pixel bei guter visueller Qualität. Da kommt man mit PNG nicht ran.

Zu guter Letzt: Gimp bietet bspw. an, transparente Farbwerte zu entfernen. Das ist fast perfekt, weil es die Entscheidung, ob sie benötigt werden, zum Künstler verschiebt. (Besser wäre nur noch, das den Nutzer der Grafik entscheiden zu lassen.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Tiles

Re: PNG mit 7-Zip

Beitrag von Tiles »

Selber schuld. Dafür gibt es Premultiplied Alpha … ;)
Och, nicht jede Gameengine kann Premultiplied. Unity kann aber premultiplied Alpha. Und trotzdem siehst du es da sehr schön. Auch premultiplied ist also kein Allheilmittel :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

Dann läuft da irgendwas falsch … Premultiplied funktioniert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Mr. Heat
Beiträge: 22
Registriert: 24.06.2008, 16:07
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Mr. Heat »

Es gibt leider Bildbearbeitungen, die in den transparenten Bereichen nur undefinierten Müll speichern. Diesen Müll zu entsorgen, zähle ich als verlustfrei. ;-) Aber natürlich kann ein Tool nicht entscheiden, ob es Müll ist.

Aufmerksam geworden bin ich darauf, weil mir an den Transparenzkanten von linear interpolierten Texturen weiße Pixel entgegen flackerten. Der transparente Bereich war aus irgend einem Grund weiß gefüllt. Das Säuberungs-Tool habe ich mir zuerst nur deshalb geschrieben. In meinem Fall (im dunklen Setting von Glow) hat eine simple schwarze Füllung das Problem schon gelöst. Quasi nebenbei hat das die PNGs besser komprimierbar gemacht.

Ideal wäre es, wenn das Tool die sichtbaren RGB-Werte drei Quadratpixel weit in den unsichtbaren Bereich hinein interpoliert und nur den Rest einfarbig füllt. Am besten mit dem Median aller Randpixel. So weit musste ich es aber gar nicht treiben. Schwarz hat mir wie gesagt gereicht.
Benutzeravatar
Krishty
Establishment
Beiträge: 8316
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Krishty »

… oder auf Premultiplied Alpha umsteigen und die Kopfschmerzen vergessen ohne Komprimierbarkeit einzubüßen ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Tiles

Re: PNG mit 7-Zip

Beitrag von Tiles »

Hm, ich will eigentlich nicht deinen Thread hijacken. Das Thema Premultiplied Alpha könnte man glatt vereinzeln. Jedenfalls siehts bei mir so wie im Bild aus. Ein transparentes rotes Kugelbild als Grasersatz. Einmal mit schwarzem unsichtbaren Hintergrund, einmal mit einem unsichtbaren Hintergrund der vom sichtbaren Bereich in den unsichtbaren erweitert wird. Sprich ich hab ne rote Kugel, und die setzt sich im unsichtbaren Bereich fort. Wie du sehr schön siehst schimmert beim linken Bildteil das Schwarz wunderbar durch. Das ist mein Kugelgras mit dem schwarzen Hintgergrund. Die rechte Hälfte nutzt die Textur mit dem erweiterten roten Hintergrund.

Ich scheine mich übrigens geirrt zu haben. Unity scheint doch kein Premultiplied Alpha zu können. In der Manual steht nur was von Straight Alpha Blending und dass man die Farben extenden muss. Womit wir wieder beim Thema nicht jede Engine kann Premultiplied Alpha wären :)
Dateianhänge
mipmapnhalo.jpg
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4273
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: PNG mit 7-Zip

Beitrag von Chromanoid »

Ich hätte sonst gedacht, dass einfach die Render-Reihenfolge falsch ist bzw. kein Z-Sorting betrieben wird. Aber hier liegt das ja wirklich am fehlenden vormultiplizieren :).
Mr. Heat
Beiträge: 22
Registriert: 24.06.2008, 16:07
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Mr. Heat »

Dank http://blog.rarepebble.com/111/premulti ... in-opengl/ habe ich es jetzt verstanden. Ich war verwirrt, weil Vormultiplizieren allein ja erst recht schwarze Ränder erzeugen würde. Genau das macht es ja: Transparente Pixel werden um so mehr abgedunkelt, je transparenter sie sind. Das ergibt nur Sinn, wenn man vormultiplizierte Texturen mit einer anderen Blend-Funktion auf den Bildschirm bringt (bei OpenGL GL_ONE, GL_ONE_MINUS_SRC_ALPHA).

Und da sind wir zurück beim Thema: Vormultiplizierte Texturen lassen sich besser PNG-komprimieren, weil die leeren Bereiche wirklich leer (mit 0,0,0 gefüllt) sind.
Tiles

Re: PNG mit 7-Zip

Beitrag von Tiles »

Mich würde da jetzt noch interessieren wie sich das Mipmapping im direkten Vergleich zwischen Premultiplied und der alten Technik von wegen Farben in den transparenten Bereich erweitern auswirkt. Gibts da nen sichtbaren Unterschied?
Benutzeravatar
Schrompf
Moderator
Beiträge: 5047
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: PNG mit 7-Zip

Beitrag von Schrompf »

Rein mathematisch müsste das Ergebnis identisch sein. Es kann sein, dass aufgrund der begrenzten Genauigkeit leichte Fehler reinkommen, aber die beschränken sich ja prinzipiell auf die nahezu durchsichtigen Bereiche, in der Praxis müsste also kein Unterschied erkennbar sein.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten