Wer dieses Blog hier regelmäßig liest, weiß, dass ich besessen bin von Datenkompression, insbesondere von verlustfreier Kompression. Und ich weiß nicht einmal besonders viel über die inneren Wirkmechanismen den Kompression. Ich bin einfach besessen davon, die Daten, die hier auf dem Server liegen, für die Übertragung möglichst klein zu kriegen.
Und jetzt, nach Jahren des Dramas, steht endlich die Unterstützung von JPEG XL in Firefox und Chromium bevor. JPEG XL ist ein relativ neuer, offener Standard für Bildkompression. Es unterstützt sowohl verlustfreie als auch verlustbehaftete Kompression (wem das nichts sagt: Ich habe mal versucht, Bilddateiformate und Bildkompression verständlich zu machen). Es soll verlustfrei besser komprimieren als WebP, bei vergleichbarer Qualität kleinere Dateien erzeugen als WebP oder AVIF (und erst recht kleiner als JPEG) und, ein Alleinstellungsmerkmal: Man kann JPEG-Dateien verlustfrei re-codieren und kriegt kleinere Ergebnisdateien mit identischem Bildinhalt. Wenn man also alte JPEG-Dateien herumliegen hat, die man nich in WebP oder AVIF umcodieren wollte, weil das ein Qualitätsverlust wäre: Hier ist die Lösung.
Bis wir aber an dem heutigen Punkt angekommen sind, gab es eine Menge Drama.
Drama
Ich habe das damals nur im Hintergrund verfolgt (viele wütende Posts auf Mastodon und anderen Kanälen), aber nachdem Google experimentelle JPEG XL-Unterstützung 2021 in Chromium eingebaut hatte, haben sie diese Ende 2022 wieder entfernt (Wikipedia-Artikel dazu). Ich habe verschiedene Begründungen dafür gelesen, aber am Ende lief es darauf hinaus, dass Google sich auf die anderen Bildformate konzentrieren wollte und ein weiteres Bildformat mehr Wartungskosten und weitere Sicherheitsrisiken erzeugt hätte.
Mozilla hat daraufhin auch den experimentellen JPEG XL-Support in Firefox gestrichen. Die Idee dahinter ist hier verständlich: Kaum eine Website wird ein Bildformat verwenden, dass vom marktbeherrschenden Browser nicht auch unterstützt wird.
Es wurden dann natürlich Stimmen laut, dass Google JPEG XL unterdrücke, um ihr eigenes Bildformat (WebP) zu pushen, und dass Mozilla JPEG XL zumindest weiter hätte unterstützen können, um Druck auf Google aufzubauen. Ich persönlich kann aber verstehen, dass Google sich den Wartungsaufwand und die potentiellen Sicherheitsprobleme mit JPEG XL ersparen wollte.
In 2024 hat Mozilla dann eingelenkt und gesagt, sie würden JPEG XL unerstützen, wenn es eine Rust-Implementierung des Decoders gibt. Und diese Implementierung gibt es. Also hat Mozilla die experimentelle Unterstützung für JPEG XL wieder in Firefox eingebaut, und Google hat das bei Chromium auch gemacht.
Dieses Drama steht kurz vor dem guten Ausgang. Firefox hat JPEG XL ab Version 158 per default aktiviert (ursprünglich war Version 157 geplant, das hat aber nicht geklappt), Chromium ab Version 155 (beide liegen aktuell noch in der Zukunft), Safari unterstützt JPEG XL (allerdings ohne Animationen) schon länger. Anderen Browser ohne Unterstützung bauen auf einem der anderen engines auf und werden vermutlich nachziehen. Und wenn nicht? Das wäre eh hauptsächlich Edge, und fuck Edge.
Erwähnenswert ist, wie ich finde, jedoch der kürzlich veröffentlichte Blogpost The case against JPEG XL. Der Autor sagt, er sei selber ein Fan von JPEG XL, hält JPEG XL im Webbrowser aber für überflüssig. Insbesondere schreibt er:
By volume, there are very few use cases on the Web that aren't served by versatile lossy compression. The average Web consumer doesn't need lossless; they just need a lossy codec versatile enough to prevent terrible artifacts. […] This rules out JPEG XL's lossless advantage, which in practice is only roughly 11.9% smaller than lossless WebP anyway […].
Ok. Ich selber bin aber besessen von der verlustfreien Kompression. Und knap 12 % bessere Kompressionsrate als WebP (was noch einmal eine Verbesserung zu PNG ist) ist schon ordentlich. Das will ich.
Test: Verlustfreie Kompression mit JPEG XL
Ich habe mal ein paar Tests durchgeführt. Verlustfreie Kompression ist da relativ gut zu testen, wenn man die Encoding-/Decoding-Geschwindigkeit ignoriert: Je kleiner, desto besser (und decoding ist hier i.d.R. deutlich schneller als encoding, was gut ist, denn die Datei muss nur einmal encodiert werden, aber oft decodiert).
Verlustbehaftete Kompression ist schwieriger zu bewerten, dazu kommt vielleicht später noch ein Post.
Ich habe drei verschiedene Testbilder in insgesamt drei Bilddateiformaten ausprobiert. Die Formate waren PNG (mit Zopflipng optimiert), WebP (mit höchster verlustfreier Kompressionsstufe) und JPEG XL (ebenfalls mit höchster verlustfreie Kompressionsstufe).
Die drei Bilder sind unterschiedlich schwierig zu komprimieren. Das erste Beispiel ist trivial: ein komplett schwarzes Bild, 1000×1000 Pixel. Das zweite Beispiel ist eines meiner Fordite-Bilder: „Tanz eines Feuergottes“:

Das ist auch sehr einfach, es sind große, einfarbige Flächen mit klaren Kanten (ohne Kantenglättung). Das dritte Bild ist Artwork aus dem Trainpunks-Rollenspiel:

Von diesem Artwork habe ich aber die Originalversion mit einer Auflösung von 1917×1719 genommen, die nie verlustbehaftet komprimiert war.
Hier sind die Befehle, die ich zum Encodieren genutzt habe:
zopflipng -m -y "input.png" "output.png"
cwebp -z 9 "input.png" -o "output.webp"
cjxl -q 100 -e 9 "input.png" "output.jxl"
Die Ergebnisse sehen so aus:
| Format | trivial | Feuergott | Trainpunks |
|---|---|---|---|
| PNG | 202 | 33974 | 2051089 |
| WebP | 82 | 22638 | 1342528 |
| JPEG XL | 64 | 16498 | 1101756 |
Die PNG-Version habe ich nur so als Baseline hinzugefügt. Das ist mit Zopflipng komprimiert, das ist so ziemlich das Beste, was man aus PNG herausholen kann (die Optimierung dauert dafür sehr lange).
Beim trivialen Bild macht sich der relative Unterschied am stärksten Bemerkbar, der absolute Unterschied ist aber vernachlässigbar, und das Bild ist sowieso eines, das keine praktische Anwendung hat.
Bei den anderen Bildern ist die WebP-Variante etwa 65 % so groß wie die PNG-Variante, während JPEG XL auf etwa 50 % kommt. Das bedeutet eine Verbesserung von 7 % bis 8 % von WebP auf JPEG XL. Das ist schon noch einmal ein ordentlicher Unterschied. Was mache ich jetzt damit?
Zukunft: JPEG XL in diesem Blog
Ich habe vor, JPEG XL auch in diesem Blog zu nutzen. Mein static site generator (in Rust geschrieben) muss allerdings die Bilddimensionen von Bilddateien aus den Headern herausfischen, um sie ins HTML einzufügen. Glücklicherweise gibt es dafür aber ja schon ein Rust-Crate, weil das ja Mozillas Bedingung war, das Format überhaupt zu unterstützen.
Wann wird das kommen? Jedenfalls nicht bevor Firefox und Chromium das Format per default aktivieren. Ansonsten würde ich mich nach der Can I Use-Seite richten. Sobald Chromium das Format kann, werden vermutlich die meisten Browser, die auf Chromium basieren, nachziehen. Wenn nicht… Das ist eh hauptsächlich Edge, und Edge-User sind nun wirklich nicht meine Zielgruppe. Außerdem schreibe ich immer Alt-Texte an meine Bilder.
Was ich auch schon länger überlege ist, dass ich ja je nach Accept-Header der HTTP-Anfrage unterschiedliche Typen ausliefern könnte. Das ist sowieso besser, wenn ich später mal meine Bilddateien im Format ändern möchte. Dann sollte ich vielleicht die Dateiendungen der Bilddateien in der URL auch weglassen, sonst könnte das zu Verwirrung führen. Meine alten JPEG-Dateien könnte ich dann auch verlustfrei in JPEG XL umwandeln und sie damit nennenswert kleiner kriegen.
Ein Problemchen, dass ich aber auch jetzt schon habe: Je nach Plattform könnte es länger dauern, bis JPEG XL-Dateien in Vorschau-Bildern (og:image meta tag) unterstützt werden. Avif zum Beispiel wird von Mastodon bis heute nicht in Vorschaubildern angezeigt.
Ich bin jedenfalls gespannt, ob und wie schnell JPEG XL Verbreitung finden wird. Und wenn ich mal Lust habe, mache ich auch noch einen kleinen nicht methodisch korrekten Vergleich zwischen verschiedenen verlustbehafteten Formaten und JPEG XL, ebenso wie oben mit den verlustfreien Formaten.