Ein verlustfreier PDF-Komprimierungsdurchlauf schreibt die interne Struktur der Datei neu, statt die Bilder darin neu zu codieren. Wir haben gemessen, was das über acht Test-PDFs tatsächlich spart. Drei von ihnen kamen in mindestens einem Modus größer heraus, und die schlechteste Verschlechterung betrug 20,8 Prozent.
Die Ersparnis hängt davon ab, wie locker die Eingabe war. Unkomprimierte Textströme schrumpften um 84 bis 90 Prozent, während eine Datei, deren Ströme bereits Flate-komprimiert waren, im Standardmodus um 31,6 Prozent schrumpfte und im Maximum-Modus um 3,0 Prozent wuchs. Ein zweiter Durchlauf änderte bei keinem Beispiel etwas, und zwei Dateien mit demselben Inhalt, aber unterschiedlicher Struktur erzeugten byte-identische Ausgabe. Nichts davon bedeutet, dass die Engine fehlerhaft ist; es bedeutet, dass eine Größenbehauptung eine Messung dahinter braucht. Die vollständige Methode, die Tabelle und die Grenzen des Tests stehen unten.
Jedes PDF-Tool hat einen Komprimieren-Button, und fast alle melden Erfolg. Dieses Wort deckt mindestens zwei sehr verschiedene Vorgänge ab, und einer davon kann dir eine größere Datei zurückgeben. Wir wollten Zahlen statt eines Versprechens, also haben wir acht PDFs mit absichtlich unterschiedlichen internen Strukturen gebaut und jede durch qpdf 11.7.0 mit denselben Argumenten laufen lassen, die unser eigenes Tool übergibt.
PDF komprimieren
Derselbe hier beschriebene qpdf-Durchlauf, kompiliert zu WebAssembly und im Tab ausgeführt. Wähle die Stufe und lies dann die Größen vorher und nachher selbst.
Was ein "PDF komprimieren"-Button tatsächlich macht
Das Erste, was man wissen sollte, ist, dass dies meist keine Bild-Neukomprimierung ist. Es ist ein strukturelles Neu-Schreiben. Ein PDF hält seine Seiten als eine Sammlung von Objekten und Strömen, und der Durchlauf packt sie aus, entfernt Duplikate, komprimiert die Ströme, die roh gespeichert waren, und schreibt eine neue Datei.
qpdf, die Engine in unserem Tool, macht das mit diesem Aufruf im Standardmodus:
--object-streams=generate --compress-streams=y --recompress-flate --compression-level=6
und dieser im Maximum-Modus, der eine höhere Stufe und Linearisierung für schnelles Web-Ansehen hinzufügt:
--object-streams=generate --compress-streams=y --recompress-flate --compression-level=9 --linearize
Beachte, was in keinem der beiden Aufrufe steht: alles, was die eingebetteten Bilder berührt. Ein struktureller Durchlauf dekodiert kein JPEG, das bereits in einem PDF sitzt, er kann ein gescanntes oder fotolastiges Dokument also nicht nennenswert verkleinern. Was er kann, ist die Ineffizienz entfernen, die sich während des Aufbaus der Datei angesammelt hat. Deshalb hängt die Ersparnis von der Eingabe ab und nicht davon, wie sehr das Tool es versucht.
Wie die Messung durchgeführt wurde
Acht Beispiele wurden erzeugt, um jeweils eine strukturelle Eigenschaft zu isolieren: eine minimale einseitige Datei, eine dreiseitige Datei, dasselbe zwanzigseitige Dokument mit komprimierten und unkomprimierten Strömen, eine hundertseitige Datei mit vielen Objekten, eine einseitige Datei, die mit einem Junk-Kommentar aufgefüllt ist, eine Datei mit einem eingebetteten JPEG und eine Datei mit einem kleinen unkomprimierten XMP-Paket. Jede Datei wurde dann mit den oben genannten Argumenten verarbeitet, im Fall des Standardmodus zweimal, und der Byte-Zähler und der SHA-256-Hash wurden jedes Mal aufgezeichnet.
- Erzeuge die Beispiele per Skript, nicht von Hand. Das macht jedes einzelne reproduzierbar und verhindert, dass der Test von den Dokumenten abhängt, die gerade zur Hand waren.
- Verwende die echten Argumente des Tools. Die Engine wird mit genau den Flags aufgerufen, die das Browser-Tool übergibt, die Zahlen beschreiben also das Produkt und nicht ein ähnlich aussehendes Experiment.
- Zeichne Bytes und Hashes auf, nicht nur einen Prozentsatz. Ein Hash beantwortet eine zweite Frage, die die Größe nicht kann: ob zwei unterschiedlich aufgebaute Eingaben als dieselbe Datei enden.
- Führe alles ein zweites Mal aus. Den Vorgang zu wiederholen, testet, ob er konvergiert, was zählt, wenn eine Oberfläche dich einlädt, den Button erneut zu drücken.
Die Zahlen
Der Standardmodus ist Stufe 6 ohne Linearisierung. Maximum ist Stufe 9 mit Linearisierung. Negative Prozentsätze bedeuten kleinere Dateien.
| Beispiel | Eingabe (B) | Standard (B) | Ändern | Maximum (B) | Ändern |
|---|---|---|---|---|---|
| 01 minimal, 1 Seite | 3,392 | 872 | -74.3% | 1,637 | -51.7% |
| 02 minimal, 3 Seiten | 9,520 | 1,475 | -84.5% | 2,513 | -73.6% |
| 03 unkomprimierter Text, 20 Seiten | 62,145 | 6,590 | -89.4% | 9,916 | -84.0% |
| 04 komprimierter Text, 20 Seiten | 9,629 | 6,590 | -31.6% | 9,916 | +3.0% |
| 05 viele Objekte, 100 Seiten | 311,281 | 30,964 | -90.1% | 45,110 | -85.5% |
| 06 lockere Struktur, 1 Seite | 7,489 | 872 | -88.4% | 1,637 | -78.1% |
| 07 eingebettetes JPEG-Bild | 67,974 | 68,124 | +0.2% | 68,863 | +1.3% |
| 08 unkomprimiertes XMP | 4,151 | 4,235 | +2.0% | 5,013 | +20.8% |
Vier Dinge, die die Zahlen sagen
Der Gewinn kommt daher, dass die Eingabe locker ist, nicht daher, dass das Tool klug ist
Dateien, deren Textströme unkomprimiert gespeichert waren, schrumpften um 84 bis 90 Prozent. Eine Datei, deren Ströme bereits Flate-komprimiert waren, schrumpfte im Standardmodus um 31,6 Prozent und wuchs dann im Maximum-Modus um 3,0 Prozent, weil Stufe 9 plus Linearisierung Struktur hinzufügte, die die Datei nicht brauchte. Mehr Aufwand ist nicht dasselbe wie eine kleinere Datei, und die Grenze ist die Struktur der Eingabe, nicht der darauf angewendete Aufwand.
Drei der acht Beispiele wurden größer
Der schlimmste Fall war ein Anstieg um 20,8 Prozent bei einer Datei mit einem kleinen unkomprimierten XMP-Paket, die durch den Maximum-Modus geschickt wurde. Das Beispiel mit einem eingebetteten JPEG wuchs in beiden Modi, weil es nichts Strukturelles zu gewinnen gab und das Neu-Schreiben selbst Bytes kostet. Das ist der Teil, den eine Erfolgsmeldung verbirgt: Ein Kompressor, der immer Erfolg meldet, misst nichts, und bei diesen Eingaben ist die ehrliche Ausgabe eine etwas größere Datei.
Der Vorgang ist idempotent auf seiner eigenen Ausgabe
Jedes Beispiel wurde ein zweites Mal durch den Standardpfad geführt, und jede Änderung im zweiten Durchlauf betrug 0,0 Prozent. Sobald eine Datei neu geschrieben wurde, findet ein erneutes Neu-Schreiben nichts. Wenn ein Tool scheint, bei jedem Tastendruck neue Ersparnisse zu finden, ist das ein Grund, sich anzusehen, was es tatsächlich tut, und kein Zeichen von Gründlichkeit.
Das Neu-Schreiben normalisiert, es beschneidet nicht bloß
Die Beispiele 01 und 06 sind dasselbe einseitige Dokument, außer dass 06 vier Kilobyte Junk-Kommentar trägt. Nach dem Neu-Schreiben erzeugen sie denselben SHA-256-Hash. Die Beispiele 03 und 04 sind dasselbe zwanzigseitige Dokument mit komprimierten und unkomprimierten Strömen, und sie konvergieren auf dieselbe Weise. Die Engine baut die Datei in eine kanonische Form um, statt wegzurasieren, was sie zufällig findet, was auch der Grund ist, warum ein zweiter Durchlauf nichts mehr zu tun hat.
Wie man erkennt, ob ein Kompressor überhaupt etwas gemessen hat
Zwei Prüfungen dauern jeweils etwa eine Minute und funktionieren mit jedem Tool.
- Verlange die Zahl. Eine Meldung, die Komprimiert sagt, ohne einen Byte-Zähler vorher und nachher, hat dir nichts gesagt. Die Fälle, die es zu beobachten lohnt, sind kleine Dateien und bereits gut gebaute Dateien, bei denen die ehrliche Antwort oft lautet, dass sie gewachsen ist.
- Versuche eine Datei, die bereits straff ist. Ein Export aus einer modernen Office-Suite ist meist bereits komprimiert. Wenn ein Tool trotzdem eine große Ersparnis dafür behauptet, codiert es entweder deine Bilder neu, was eine Qualitätsentscheidung statt einer verlustfreien ist, oder es rät.
Beide Prüfungen weisen auf dieselbe Idee hin. Ein struktureller Optimierer hat keine Zielgröße, auf die er hinarbeiten kann, weshalb unser eigenes Tool kein Feld dafür hat und weshalb die ehrliche Beschreibung dessen, was es kann, vom Dokument vor ihm abhängt.
Wo dieser Test Grenzen hat
Die Zahlen oben sind real und sie sind eng begrenzt. Klarheit über die Lücken ist der Sinn ihrer Veröffentlichung.
- Die Beispiele werden erzeugt, nicht gesammelt. Sie isolieren absichtlich strukturelle Eigenschaften, sie sind also keine Zufallsstichprobe der PDFs, die Leute tatsächlich haben.
- Acht ist ein kleiner Satz. Lies die Prozentsätze als Beleg dafür, dass eine Spanne existiert, nicht als Durchschnitt für alle PDFs.
- Bilder werden durch ein Beispiel repräsentiert. Ein einzelnes eingebettetes JPEG steht für eine ganze Klasse von Dokumenten. Tieferes Verschachteln von Bildern, Schriftarten und Formularfeldern wurde nicht getestet.
- Die Engine codiert hier nie Bilder neu. Das ist eine Eigenschaft des strukturellen Durchlaufs von qpdf und nichts, was dieser Datensatz über andere Kompressoren beweist.
- Versionen zählen. Diese Ergebnisse gehören zu qpdf 11.7.0. Wenn eine spätere Version ihre Optimierung ändert, ändern sich die Zahlen mit ihr und die Methode muss erneut durchgeführt werden.
Häufig gestellte Fragen
Wenn du das größere Bild davon willst, was ein Browser-Tool mit einem Dokument kann und nicht kann, die Anleitung zu ein PDF ohne Upload komprimieren behandelt die Engine und den Dateipfad, und die Frage der Zielgrößen erklärt, warum ein verlustfreier Optimierer kein Feld dafür hat.