Patu

Eine Qualitätszahl lügt: was ssimulacra2 stattdessen misst

Jeder Bild-Encoder hat einen Qualitätsregler – -q 80, -quality 90, ein cq-level. Das fühlt sich wie ein Versprechen an: auf 80 stellen, und jedes Bild kommt „80% gut" heraus. Ist es nicht. Die Zahl setzt einen Kompressions-Parameter, kein Ergebnis, und das Ergebnis hängt vollständig vom Bild ab.

Wir können genau zeigen, wie sehr sie lügt.

Dieselbe Einstellung, wild unterschiedliche Qualität

Wir haben 1.998 echte Fotografien mit einem festen -q 80 (libjpeg-turbo) zu JPEG encodiert und jedes einzelne mit ssimulacra2 bewertet, einer wahrnehmungsbasierten Metrik, bei der höher näher am Original bedeutet.

vips -q 80 bei 1.998 Fotos ssimulacra2
schlechtestes Bild 58
10. Perzentil 74
Median 77
90. Perzentil 80
bestes Bild 87

Eine Einstellung. Eine Spanne von 29 Punkten in der tatsächlichen Qualität. Bei -q 80 kommt ein Foto bei 58 heraus – sichtbar degradiert, blockig und matschig – während ein anderes bei 87 landet, nicht vom Original zu unterscheiden und mit Bytes belastet, die es nicht gebraucht hätte. Die Zahl am Regler sagte über keins der beiden etwas aus.

Über Encoder hinweg wird es schlimmer. -q 80 in JPEG ist nicht -q 80 in WebP ist nicht cq-level 30 in AVIF – jede Skala wird von ihrem eigenen Encoder definiert, dieselben Ziffern bedeuten also etwas anderes. Eine Qualitätszahl ist nicht einmal mit sich selbst in einem anderen Tool vergleichbar.

Warum der Inhalt eines Fotos über seine Qualität entscheidet

Eine Qualitätseinstellung legt fest, wie aggressiv Details verworfen werden. Ein flacher Himmel oder ein weiches Porträt haben wenig Detail zu verlieren, aggressive Einstellungen schaden also kaum – der Wert fällt hoch aus. Ein Foto von Laub, Kies oder Stoff besteht nur aus feinen Details, dieselbe Einstellung zerlegt es also – der Wert fällt niedrig aus. Der Encoder wandte dieselbe Regel an; die Bilder hatten völlig unterschiedlich viel zu verlieren.

Deshalb liefert „nimm einfach Qualität 80" im Stillen gleich zwei Fehler auf einmal: manche Bilder degradiert bis über den Punkt, an dem ein Nutzer es bemerkt, und manche Bilder 30% größer, als sie sein müssten. Man sieht es nicht in den Einstellungen – nur in der Ausgabe.

Worauf man stattdessen zielen sollte

Ziel ist das Ergebnis, nicht der Parameter. ssimulacra2 ist genau dafür gebaut: Es ist in Einheiten wahrgenommenen Unterschieds kalibriert (grob gesagt „gerade noch wahrnehmbare Unterschiede" zum Original), ein Zielwert bedeutet also bei jedem Bild und in jedem Format dasselbe.

Ein Ziel wählen und dann die Encoder-Qualität pro Bild suchen lassen, um es zu treffen. Das Laubfoto bekommt eine höhere Qualitätseinstellung, weil es eine braucht; der flache Himmel bekommt eine niedrigere, weil er es kann. Jedes Bild landet bei derselben wahrgenommenen Qualität, jeweils mit den wenigsten Bytes, die dafür nötig sind. Kein Bild wird im Stillen ruiniert, keins im Stillen aufgebläht.

Genau das macht Patu bei jedem Bild: eine Suche der Encoder-Qualität pro Bild, um einen ssimulacra2-Zielwert zu treffen, statt eines festen -q, der bei jedem Foto etwas anderes bedeutet.

curl -X POST "https://patu.dev/v1/compress?target=85" \
  -H "X-Api-Key: $PATU_KEY" \
  --data-binary @photo.jpg -o photo.avif

Die Metrik leistet die Arbeit, die eine Qualitätszahl nur vorgibt zu leisten: das Bild zu beschreiben, das man tatsächlich bekommt.


Methode und Daten: das Patu-Benchmark-Testsystem über die Foto-Kategorie (1.998 echte Fotografien); libjpeg-turbo über vips; bewertet mit ssimulacra2 über die rust-av-Implementierung. Die Perzentile beziehen sich auf alle bewerteten Bilder bei der festen Einstellung.