Warum ändert sich die Dateigröße, wenn ein Bild verlustfrei gedreht wird?

37

Ich habe nach Methoden der verlustfreien Bildrotation gesucht und bin auf diese Frage gestoßen, die es ziemlich gut erklärt:

Sind "Windows Photo Viewer" -Rotationen verlustfrei?

Also habe ich ein 256 × 256 JPEG mit zufälligen Pixeln erstellt (Photoshop Cloud Filter) und es dann mit Windows Picture Viewer gedreht. Nach der Drehung vergrößerte sich die Dateigröße tatsächlich, jedoch nur bei der ersten Drehung. Bei jeder nachfolgenden Drehung blieb die Dateigröße statisch. Ich weiß, dass es verlustfrei rotiert, weil ich es mehrere Male gedreht habe, ohne merklichen Qualitätsverlust, während ein 257 × 257-Bild, das 20 Mal gedreht wurde, sehr verlustreich wurde.

oscilatingcretin
quelle
8
Um wie viel hat sich die Dateigröße in Ihren Tests erhöht?
James Snell
3
@ JamesSnell Ich wusste, dass ich das hätte aufnehmen sollen. Das, was ich gerade mit dem GIMP-Filter für Differenzclounds gemacht habe, war ursprünglich 14.583 Byte, wurde aber nach der Roation auf 23.638 Byte geändert. Das ist eine Differenz von über 9000 Bytes, was eine Menge zusätzlicher Daten zu sein scheint, wenn wir nur über Metadaten reden.
Oscilatingcretin
4
Das scheint eine Menge zusätzlicher Metadaten zu sein. Ich würde nicht zu schnell davon ausgehen, dass all diese zusätzlichen Daten Metadaten sind. Mir scheint, dass der Größenunterschied aufgrund von Metadaten fast konstant sein sollte (auf wenige Bytes genau, um die Zeichenfolgendarstellung einiger Zahlen zu berücksichtigen).
Scottbb
4
Wenn Sie zusätzliche Informationen bereitstellen, die für die Frage relevant sind, bearbeiten Sie diese bitte in der Frage und nicht in den Kommentaren. Kommentare sind kurzlebig und können von Zeit zu Zeit bereinigt werden.
Scottbb
2
Das Hochladen der Originalversion Ihres Testbildes ist hilfreich.
CodesInChaos

Antworten:

36

Dies wird höchstwahrscheinlich durch die Entropiecodierung verursacht , die die letzte verlustfreie Stufe der JPEG-Komprimierung darstellt, nachdem die Bilddaten quantisiert wurden, um ihre Größe zu verringern.

Wenn ein JPEG-Bild verlustfrei gedreht wird, muss diese letzte verlustfreie Codierschicht rückgängig gemacht werden, die entpackten DCT-Koeffizienten müssen herumgemischt werden, und dann müssen die gemischten Koeffizienten erneut entropiecodiert werden. Da die Effizienz der Entropiecodierschicht von der Reihenfolge der DCT-Koeffizienten in jedem Block abhängt, die sich beim Drehen des Bildes ändern, sollte es nicht überraschen, dass die gedrehte Bilddatei einige Prozent kleiner oder größer als das Original sein kann.

Es gibt auch verschiedene Möglichkeiten, wie der Schritt der Entropiecodierung durchgeführt werden kann. Daher ist es durchaus möglich, dass die Dateigröße des exakt gleichen JPEG-Bildes abhängig von der Software, die die Codierung vornimmt, variiert. Zu den möglichen Unterschieden zwischen Encodern gehören:

  • Wahl der arithmetischen Codierung (selten, aber möglicherweise effizienter, patentiert) vs. Huffman-Codierung (einfacher, Standard);
  • Wahl der sequentiellen (jeder 8 × 8-Pixel-Block wird einzeln codiert) vs. progressiven (Niederfrequenzkomponenten aller Blöcke werden vor den Hochfrequenzkomponenten codiert, normalerweise etwas kompakter) Codierungsreihenfolge;
  • Auswahl der Standard-Huffman-Symboltabellen (schneller, einfacher, möglicherweise effizienter für sehr kleine Bilder) im Vergleich zu benutzerdefinierten Tabellen, die für jedes Bild optimiert sind (normalerweise effizienter für große Bilder, langsamer und komplexer zu codieren);
  • Wenn benutzerdefinierte Huffman-Tabellen verwendet werden, können unterschiedliche Codierer möglicherweise unterschiedliche Tabellen für dieselben Bilddaten generieren.
  • Verschiedene Details auf niedriger Ebene des Codierungsprozesses selbst, z. B. ob und wann Neustartmarkierungen in den Datenstrom aufgenommen werden sollen, können auch zwischen den Codierern variieren.

Außerdem enthalten die "JPEG-Dateien", mit denen normalerweise gearbeitet wird, JPEG-komprimierte Bilddaten, die in einem JFIF- oder einem Exif- Container eingeschlossen sind, der die Bilddaten mit einem oder mehreren Metadatenblöcken kombiniert und eigene Komplikationen einführt. Auch wenn die Software, mit der das Bild gedreht wird, keine wesentlichen Änderungen an den JFIF / Exif-Metadaten vornimmt, kann sich eine einfache Neuanordnung der Daten möglicherweise auf die Dateigröße um einige Bytes auswirken.

Insbesondere können die JFIF / Exif-Metadaten eine oder mehrere Miniaturansichten des Vollbilds enthalten , und Software, die Bilder dreht, sollte die Miniaturansichten wirklich neu generieren (oder auch verlustfrei drehen!), Damit sie der neuen Ausrichtung des Vollbilds entsprechen. Bildgröße. Dies allein könnte leicht den beobachteten Größenunterschied erklären.

Ilmari Karonen
quelle
4
Bei einer Differenz von 9 KB (60%) würde ich davon ausgehen, dass es sich um Thumbnails handelt.
BlueRaja - Danny Pflughoeft
JPEG ist möglicherweise zu einfach, als dass es sich für Encoder lohnt, dies zu tun, aber Video-Encoder wie x264 können tatsächlich die Fähigkeit des Eingabecoders in Betracht ziehen, zu codieren, was sie als Nächstes ausgeben, wenn sie Kompromissentscheidungen zwischen Rate und Verzerrung treffen. (dh zu entscheiden, wie viele Bits jede Alternative kosten könnte, und dies gegen den verlustbehafteten Fehler abzuwägen). Dies wird als Trellis-Quantisierung bezeichnet. Siehe Hinweise zur Implementierung der Trellis-Quantisierung in H.264 vom Autor von x264 (Loren Merritt); Er beginnt mit einer ziemlich einfachen Erklärung des Zwecks.
Peter Cordes
Wie auch immer, der JPEG-Codierer hat möglicherweise DCT-Koeffizienten so ausgewählt, dass sie mit dem Entropiecodierer gut komprimiert wurden, sodass selbst ein optimaler Kompressor eine gedrehte Version nicht so klein machen kann. (Eine andere Reihenfolge würde wahrscheinlich zu einer schlechteren Komprimierung führen.) Dies wäre mit ziemlicher Sicherheit ein kleiner Effekt für JPEG, da jeder 8x8-Block separat codiert wird (Zurücksetzen des Entropiecodierers AFAIK). (I-Frames in h.264 verwenden Intra-Prädiktion und prognostizieren aus anderen Blöcken im selben Frame, wodurch sie kleiner als ein JPEG bei gleicher visueller Qualität sind.)
Peter Cordes,
24

Ich ging weiter und wiederholte das Experiment, um herauszufinden, was los ist.

Verfahren

Ich habe mit dem Filter "Solid Noise" in GIMP (Filter> Rendern> Wolken> Solid Noise ...) mit den Standardeinstellungen (siehe unten) ein zufälliges RGB-Bild mit 256 x 256 Pixeln erzeugt:

Bildbeschreibung hier eingeben

Und das Ergebnis:

Bildbeschreibung hier eingeben

Dann habe ich das Bild mit den Standardeinstellungen als JPEG gespeichert:

Bildbeschreibung hier eingeben

Dann habe ich das Bild auf Windows übertragen und es mit Windows Photo Viewer geöffnet, indem ich mit der rechten Maustaste auf das Bild im Datei-Explorer geklickt und im Menü die Option Vorschau ausgewählt habe. Dann habe ich das Bild mithilfe der Schaltflächen unten gedreht und es gespeichert, indem ich mit den Pfeiltasten zum nächsten Bild navigiert habe.

Für jeden der folgenden Tests habe ich mit einer Kopie des Originalbilds begonnen und vor dem Speichern die entsprechende Anzahl von Drehungen (Klicken auf die Schaltfläche "Drehen") vorgenommen. Hier sind die Größen ( ls -l -r):

                    size in bytes    last-modified date 
                          VVVVV        VVVVV
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:24 original.jpg
-rwxrwx--- 1 root vboxsf  23645 Nov  8 11:30 cw.jpg
-rwxrwx--- 1 root vboxsf  23636 Nov  8 11:30 cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:30 cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:27 cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:31 cw-cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:29 ccw.jpg
-rwxrwx--- 1 root vboxsf  23636 Nov  8 11:29 ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf  23645 Nov  8 11:29 ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:27 ccw-ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:30 ccw-ccw-ccw-ccw-ccw.jpg

Sofortige Beobachtungen

  • Windows Photo Viewer (WPV) vergrößert sich dramatisch. In diesem Test beträgt die Erhöhung etwa das Vierfache!
  • Alle neuen Bilder werden ungefähr gleich groß, sind jedoch nicht identisch.
  • WPV kodiert das Bild nicht neu oder speichert es nicht einmal neu, wenn es um ein Vielfaches von 360 Grad gedreht wird. (Der Zeitstempel 11:27 ist der Zeitpunkt, an dem die Dateien zum ersten Mal kopiert wurden.)

Durch die Verwendung cmp -lvon Dateien mit identischem Inhalt können wir feststellen, wo sich die Dateien unterscheiden.

robert@unity ../jpeg-rotate-test % cmp -l cw.jpg ccw-ccw-ccw.jpg
 2223  63  62
 2224  60  71
 2226  60  64
 2227  60  66
robert@unity ../jpeg-rotate-test % cmp -l cw-cw.jpg ccw-ccw.jpg
 2223  63  62
 2224  60  71
 2226  60  64
 2227  62  64
robert@unity ..jpeg-rotate-test % cmp -l ccw.jpg cw-cw-cw.jpg
 2223  62  63
 2224  71  60
 2226  64  60
 2227  61  64
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg cw-cw-cw-cw-cw.jpg
 2221  60  61
 2223  63  61
 2224  60  66
 2226  60  61
 2227  60  61
robert@unity ../jpeg-rotate-test % cmp -l ccw.jpg ccw-ccw-ccw-ccw-ccw.jpg
 2223  62  63
 2224  71  60
 2226  64  65
 2227  61  64

Diese Dateien unterscheiden sich in nur vier Bytes (tatsächlich in einem Zeitstempel), was bedeutet, dass WPV jedes Mal das Gleiche tut. Jetzt müssen wir nur noch herausfinden, was das ist.

Detaillierte Beobachtungen

Dafür habe ich JPEGsnoop verwendet, um zu sehen, was genau in den Bildern enthalten ist.

Da die Ausgaben ziemlich lang sind, habe ich sie als Kern verlinkt . Hier ist eine Zusammenfassung der Unterschiede:

  • GIMP verwendet nur ein APP0(JFIF-) und ein COM(Kommentar-) Segment für Metadaten. WPV lässt das APP0Segment unangetastet, fügt dem Kommentar aber merkwürdigerweise ein Null-Byte hinzu (so dass es nullterminiert ist).

  • WPV fügt zwei APP1Segmente hinzu, nämlich Exif- und XMP-Metadaten. Diese Segmente haben eine Größe von 4286 bzw. 12726 Byte. Zusammen machen sie fast die gesamte Zunahme der Dateigröße aus.

  • GIMP erzeugt ein progressives JPEG, während WPV ein Basis-JPEG (nicht-progressives JPEG) erzeugt. Aus diesem Grund hat das Bild von GIMP mehrere Scan-Segmente, während das WPV-Bild nur ein einziges hat. Nach meiner Erfahrung ist das progressive Bild manchmal etwas kleiner.

  • GIMP verwendete eine 1 × 1-Chroma-Unterabtastung, während WPV eine 2 × 2-Unterabtastung verwendete. Dies lässt mich glauben, dass WPV keine "echte" verlustfreie Rotation verwendet, es sei denn, es kann irgendwie erkennen, dass es sich um ein Schwarzweißbild handelt.

Um diese Probleme zu beheben, habe ich einen zweiten Test durchgeführt.

Verfahren

Ich habe ähnliche Schritte wie beim ersten Test ausgeführt. Ich habe mit dem RGB-Rauschfilter (Filter> Nase> RGB-Nase ...) ein zufälliges 256 × 256-RGB-Bild mit den folgenden Einstellungen erstellt:

Bildbeschreibung hier eingeben

Hier ist das Ergebnis:

Bildbeschreibung hier eingeben

Ich habe die Datei mit den folgenden Einstellungen als JPEG exportiert:

Bildbeschreibung hier eingeben

Progressive wurde deaktiviert , die Unterabtastung ist jedoch weiterhin auf 4: 4: 4 eingestellt (ein anderer Name für 1 × 1-Unterabtastung). Die Qualität wird auf 98 erhöht.

Ich habe das Bild kopiert und die Kopie im Uhrzeigersinn gedreht. kopierte dann die gedrehte Version und drehte diese Kopie gegen den Uhrzeigersinn, so dass wir die Qualität zwischen der Originalkopie und der von WPV verarbeiteten Kopie direkt vergleichen können.

Ergebnisse

-rwxrwx--- 1 root vboxsf 159774 Nov  8 16:21 original-random.jpg
-rwxrwx--- 1 root vboxsf 222404 Nov  8 16:24 cw-random.jpg
-rwxrwx--- 1 root vboxsf 222467 Nov  8 16:24 cw-ccw-random.jpg

Obwohl der Anstieg dieses Mal relativ gesehen geringer ist (um 40%), ist der absolute Anstieg sogar noch größer - um 62 kB. Dies deutet darauf hin, dass WMV eine weniger effiziente Codierung verwendet.

Ich werde ImageMagick verwenden , um die beiden Bilder zu vergleichen:

robert@unity ../jpeg-rotate-test % compare -verbose -metric AE original-random.jpg cw-ccw-random.jpg null:
original-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 160KB 0.000u 0:00.009
cw-ccw-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 222KB 0.010u 0:00.010
Image: original-random.jpg
  Channel distortion: AE
    red: 0
    green: 0
    blue: 0
    all: 0
original-random.jpg=> JPEG 256x256 256x256+0+0 8-bit sRGB 0.050u 0:00.020

Zwischen der Originalkopie und der gedrehten Kopie gibt es keine unterschiedlichen Pixel . Selbst wenn WPV keine "echte" verlustfreie Rotation verwendet, leistet es gute Arbeit. Ich vermute, ich weiß, was los ist, und um zu erklären, ich werde ein wenig in die Mathematik hinter der JPEG-Komprimierung umleiten.

Der JPEG-Komprimierungsalgorithmus unterteilt ein Bild in 8 × 8-Pixel-Blöcke. Jeder dieser Blöcke wird dann einer diskreten Kosinustransformation (DCT) unterzogen . Die resultierenden DCT-Koeffizienten beschreiben den Block als eine Summe von Wellen unterschiedlicher Frequenz. Der Algorithmus "wirft" dann einige Informationen in den Hochfrequenzwellen weg, die Rauschen und sehr kleinen Details entsprechen. Der Decodierungsprozess kehrt die DCT um und addiert die gespeicherten Wellen, um den Block zurückzugewinnen.

Es ist möglich, die DCT- "Wellen" zu drehen, ohne die Transformation rückgängig zu machen und zu wiederholen (im Grunde genommen wandeln Sie alle horizontalen Wellen in vertikale Wellen um und umgekehrt). Was ich denke, passiert in WPV, dass das Bild tatsächlich dekodiert, gedreht und dann neu kodiert wird. Während des Neucodierungsprozesses entspricht jeder der neuen Blöcke einem der ursprünglichen Blöcke, da die Größe unseres Bildes in beiden Dimensionen ein Vielfaches von 8 ist. Da jeder Block keine Hochfrequenzkomponenten hat, wirft der Algorithmus keine Informationen weg und findet genau die richtigen DCT-Komponenten, die eine "echte" verlustfreie Rotation haben würde.

Zuletzt werde ich noch einmal die Komponenten der JPEG-Dateien betrachten. Die Ergebnisse sind wieder als Kernpunkte verknüpft . Vergleich der beiden:

  • Das WPV-Image enthält zusätzliche 4286 + 2 Byte Exif-Metadaten, 1 zusätzliches Byte im Kommentar und 12.726 + 2 Byte XMP-Metadaten. Dies sind insgesamt 17.017 Bytes an zusätzlichen Metadaten. Wofür werden all diese Daten verwendet? Ich habe mit meinem vertrauenswürdigen Hex-Editor und einer Kopie der relevanten Standards in die Datei geschaut:

    • Exif - Metadaten wie ein TIFF - Bild aufgebaut ist, die eine Anzahl von Tags enthält (es gibt Art und Weise mehr Komplexität, aber ich bin gleich es überspringen). Die meisten Bytes im Exif-Segment befinden sich in zwei identischen Tags mit der Tag-Nummer EA1C(59.932 Dezimalstellen). Diese Tag-Nummer ist nirgendwo dokumentiert, wo ich sie finden könnte. Beide Tags enthalten 2060 Bytes vom Typ "undefined", die bis auf die ersten sechs ( 1C EA 00 00 00 08) alle Nullbytes sind . Ich habe keine Ahnung, was diese Tags sind, warum es zwei gibt und warum sie jeweils 2 kB groß sein müssen.

    • Die XMP-Metadaten sind eigentlich ein ganzes eingebettetes XML-Dokument mit Namespace und langen UUIDs, das nur die WPV-Versionszeichenfolge enthält (die bereits in den Exif-Metadaten enthalten war). Dies macht jedoch nur ungefähr 400 Bytes aus. Der Rest des Segments besteht aus 122 Wiederholungen von 100 Stellen, gefolgt von einer neuen Zeile . Das sind über 12.000 Byte völlig verschwendeten Speicherplatz.

  • Wie beim vorherigen Test verwenden sowohl GIMP als auch WPV die gleichen DCT-Quantisierungstabellen. Dies bedeutet, dass sie exakt dieselben DCT-Koeffizienten berechnen sollten, weshalb die Bilder exakt dieselben sind. Ich bin nicht sicher, ob WPV zufällig die gleichen Quantisierungstabellen verwendet oder ob es die Tabellen von der Eingabe kopiert.

  • Im Gegensatz zum vorherigen Test verwendet WPV dieses Mal eine 1 × 1-Unterabtastung, sodass möglicherweise tatsächlich erkannt wird, dass es sich um ein Farbbild handelt (oder dass zumindest höhere Abtastwerte erforderlich sind, um das Bild verlustfrei neu zu codieren).

  • GIMP und WPV verwenden unterschiedliche Huffman-Tabellen (Teil des Entropiecodierungsschritts). Die Tabellen für WPV sind um insgesamt 279 Byte größer und enthalten in einem Fall siebenmal so viele Codes.

    Wenn wir uns die Statistiken von JPEGsnoop ansehen, können wir feststellen, dass einige dieser Codes nur selten verwendet werden. Beispielsweise werden in der ID: 1, Class: ACTabelle von den 119 definierten 16-Bit-Codes nur 23 tatsächlich verwendet. Insgesamt ist das tatsächliche Scan-Segment in der WPV-Version um 28,5% größer.

Zusammenfassung

  • WPV macht möglicherweise keine "echten" verlustfreien Rotationen, aber die Rotationen scheinen praktisch verlustfrei zu sein.

  • Die zusätzliche Größe ist teilweise auf eine feste Menge hinzugefügter Metadaten und teilweise auf eine weniger effiziente Entropiecodierung zurückzuführen.

Versionsinformation:

  • Betriebssystem (Linux) ( uname -a):

    Linux unity 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux
    
  • Betriebssystem (Windows):

    Bildbeschreibung hier eingeben

  • GIMP (Linux): 2.8.14 (aus Paket gimp, Version 2.8.14-1+deb8u1)

    Bildbeschreibung hier eingeben

  • Window Photo Viewer (gemäß Bildmetadaten):

    Microsoft Windows Photo Viewer 10.0.10586.0
    
2012rcampion
quelle
20

BEARBEITEN : Diese Antwort wurde veröffentlicht, bevor ich wusste, dass sich die Größe der Dateien um 9 KB erhöht hatte (9055 Byte für das 256 × 256-Bild, 9612 KB für das 512 × 512-Bild).

Höchstwahrscheinlich hat Windows Picture Viewer beim ersten Drehen des Bildes eine (oder beide) der folgenden Aktionen ausgeführt:

  1. Es wurde ein EXIF-Tag hinzugefügt, das sich nicht im ursprünglichen JPEG-Bild befand (möglicherweise das Orientierungs-Tag).
  2. Geänderte / hinzugefügte Informationen zu einem bereits vorhandenen Tag (möglicherweise Processing Software- oder Image Software-Tags).

Dies erhöhte die Dateigröße aufgrund des zusätzlichen EXIF-Tags (und / oder zusätzlicher Daten zu vorhandenen Tags).

Durch nachfolgende Rotationen wurde die Dateigröße nicht erhöht, da alle Tags und / oder Tag-Daten, die WPV hinzugefügt / geändert hätte, bereits vorhanden waren. Nur der Wert des Ausrichtungs-Tags wurde geändert (und möglicherweise auch Datums- / Uhrzeit-Tag-Werte).


BEARBEITEN : Es ist fast sicher, dass diese Erklärung etwa 9 KB zusätzlicher Daten in der Datei nicht berücksichtigen kann. Ferner würde diese Erklärung, ohne irgendwelche anderen Gründe für die Größenerhöhung, erwarten, dass die Größenerhöhung mehr oder weniger konstant wäre (modulo einige Längenunterschiede zwischen Zeichenfolgendarstellungen von numerischen Daten, wahrscheinlich einige Bytes). Das ist offensichtlich nicht das, was hier passiert, zumindest nicht die vollständige Erklärung.

scottbb
quelle
1
Und ein EXIF-Tag wird 9 KB aufnehmen? Zumindest ist dies einfach zu testen. Lassen Sie das OP EXIF ​​oder andere Tags aus dem gedrehten Bild löschen und sehen Sie, wie sich die Dateigröße ändert.
Carl Witthoft
2
@CarlWitthoft die 9kB sind neue Informationen. Bearbeiten, um das zu erwähnen.
Scottbb
3

Ohne Reverse Engineering des JPEG-En / Decoders ist es unmöglich, sicher zu sagen. Es gibt tatsächlich eine Reihe von JPEG-Standards und entgegen der landläufigen Meinung können nicht alle ohne Neucodierung geändert werden.

Es ist möglich , dass die ersten Speicher ist ein verlustbehaftetes Rewrite in seinen bevorzugten JPEG Geschmack und die nachfolgenden Rotationen sind eine einfache Metadaten zwicken oder eine Operation direkt auf der DCT - Tabelle (die für einige Codierungsschemata möglich ist).

Die Zunahme der Dateigröße kann auch einige zusätzliche Metadaten enthalten, obwohl 9k viel zu sein scheint, ist es möglich. Der Anstieg kann auch durch das Hinzufügen eines Thumbnails erklärt werden, das in der Ausgabe von GIMP möglicherweise nicht vorhanden war. Möglicherweise können wir weitere Informationen direkt aus den Dateien abrufen (vor und nach WPV).

Auf jeden Fall ist der Versuch, ohne Probleme mit JPEG zu arbeiten, ein Kinderspiel, da er nur bei bestimmten Bildgrößen nützlich ist, nicht alle Decoder und Encoder identisch sind und diese Editoren direkt mit dem JPEG-Inhalt arbeiten müssen, auf den Sie sich nicht verlassen können der Fall ... Nur weil es jetzt so ist, heißt das nicht, dass es auch in Zukunft so bleiben wird.

Ihre bessere Wette ist es, mit einem verlustfreien Format zu arbeiten und die Schmerzen vollständig zu vermeiden.

James Snell
quelle
2
Ich bin überhaupt nicht davon überzeugt, dass das Drehen von JPEG-Daten in erster Linie zu einer Neukodierung führen sollte.
Carl Witthoft
Kommt drauf an, ob du ein Programmierer bist oder nicht ... Vermutlich bist du es nicht. Sie müssten speziell nach dieser Optimierung suchen, um diese minimale Änderung vorzunehmen, da sonst ein Speichervorgang von der unkomprimierten Bitmap ausgehen würde.
James Snell
3
Aus der verknüpften Frage geht hervor, dass Windows Photo Viewer JPEGs verlustfrei dreht.
Vclaw
2
@James Ich bin kein Low-Level-Programmierer, obwohl ich im Fernsehen spiele :-). Das OP enthielt einen Link zu einer genauen Beschreibung, wann eine Neucodierung stattfinden würde und wann nicht. Ich hatte aus dieser Diskussion gefolgert, dass er sich nur um $ \ frac {\ pi} {2} $ gedreht hatte. Ich bin damit einverstanden, dass eine willkürliche Winkeldrehung eine Neucodierung verursacht und zu einem Informationsverlust führen wird, sofern das X-by-Y-Bild nicht in einen Bereich eingebettet ist, der mindestens so groß ist wie die Hypotenuse.
Carl Witthoft
1
Wir sind uns ziemlich sicher, dass WPV für Bilder mit einer Größe von 8/16 umkehrbar gedreht wird. Siehe @ Tristans Kommentar zu Matt Grums Antwort auf die Frage im OP. Tristan hat im WPV-Team von Microsoft gearbeitet und bestätigt dies im Grunde genommen.
Scottbb
1

Eine verlustfreie JPEG-Drehung ist nur möglich, wenn die Bildabmessungen ein Vielfaches der Blockgröße betragen (normalerweise [/ always?] 8), ohne dass Randartefakte eingefügt werden. In der jpegtran-Manpage (Entschuldigung, ich habe keinen guten kanonischen Link dafür; wenn Sie einen finden, können Sie ihn gerne bearbeiten) finden Sie Details zu den Themen:

Die Transponierungstransformation unterliegt keinen Einschränkungen hinsichtlich der
Bildabmessungen. Die anderen Transformationen funktionieren ziemlich seltsam, wenn die Bilddimensionen nicht ein Vielfaches der iMCU-Größe (normalerweise 8 oder 16 Pixel) betragen, da sie nur vollständige Blöcke von DCT-Koeffizientendaten auf die gewünschte Weise transformieren können.

Das Standardverhalten von jpegtran beim Transformieren eines Bildes mit ungerader Größe wurde
entwickelt, um die exakte Reversibilität und mathematische
Konsistenz des Transformationssatzes zu gewährleisten. Wie bereits erwähnt, kann die Transponierung
den gesamten Bildbereich spiegeln. Die horizontale Spiegelung lässt eine teilweise iMCU-Spalte am rechten Rand unberührt, kann jedoch alle Bildzeilen spiegeln. In ähnlicher Weise bleibt bei der vertikalen Spiegelung eine partielle iMCU-Zeile am unteren Rand unberührt, es können jedoch alle Spalten umgedreht werden. Die anderen Transformationen können als Sequenzen von Transponierungs- und Flip-Operationen aufgebaut werden. Aus Konsistenzgründen sind ihre Aktionen auf Kantenpixeln so definiert, dass sie mit dem Endergebnis der entsprechenden Transponierungs- und Flipsequenz übereinstimmen.

Für den praktischen Gebrauch ist es möglicherweise
besser, nicht
transformierbare Kantenpixel zu verwerfen, als einen seltsam aussehenden Streifen entlang der rechten und / oder unteren Kante eines transformierten Bildes zu haben. Fügen Sie dazu den Schalter -trim hinzu:

Ich vermute, der Windows Photo Viewer vermeidet dieses Problem, indem er eine Dekomprimierung und eine Rekomprimierung mit extrem hoher Qualität durchführt, um ein verlustfreies Verhalten zu simulieren, wenn die Bildabmessungen nicht ein Vielfaches von 8 sind, anstatt tatsächlich eine verlustfreie Drehung durchzuführen. Mit einem guten Dienstprogramm können nur tatsächliche Verluste, Artefakte und alles oder ein paar Pixel gelöscht werden, anstatt die Qualität des gesamten Bilds zu beeinträchtigen (und die Dateigröße zu erhöhen).

R ..
quelle
1
irrelevant für ein 256x256 Bild.
8.
Ich habe falsch gelesen und dachte, das Problem sei für die 257x257-Version.
R ..
0

Ich habe keine definitive Antwort, aber einige mögliche Theorien, warum das passiert ist. Einige Dateitypen funktionieren so, dass zwei unterschiedliche Codes für ein Bild dieses Dateityps nicht unbedingt unterschiedliche Bilder erzeugen. Der Dateityp PNG funktioniert beispielsweise so, weil er einen transparenten Hintergrund zulässt, aber ein Bild mit einem transparenten und einem identischen Hintergrund, mit der Ausnahme, dass derselbe Hintergrund weiß ist, genauso angezeigt wird. Eine Bilddatei wird als komprimiert bezeichnet, wenn sie weniger als 3 Bytes Speicher pro Pixel belegt. Ich glaube, dass bis auf diejenigen mit transparentem Hintergrund keine zwei PNG-Dateien genau dasselbe Bild erzeugen. Wann immer Sie ein Bild als PNG speichern, konvertiert es es in einen Code, der das Originalbild erzeugt, und abgesehen von sehr ungewöhnlichen Bildern wie einem, bei dem jedes Pixel eine zufällige Farbe aller 2 ^ 24 Farben ist. Der Code benötigt weniger Speicher als 3 Bytes pro Pixel. Das Speichern von PNG wird daher als verlustfreie Komprimierung bezeichnet. Um Speicherplatz zu sparen, können jedoch nur bestimmte Bilder durch den Code einer JPEG-Bilddatei generiert werden. Es gibt wahrscheinlich mehr als einen JPEG-Dateityp und ich weiß nicht, ob einer von ihnen die Eigenschaft hat, dass zwei verschiedene Bilder dieses Dateityps genau dasselbe Bild erzeugen können. Ich gehe davon aus, dass Sie ein Bild ein paarmal gedreht und dann als JPEG gespeichert haben, um zu erklären, was unter der Annahme geschehen ist, dass Sie genau das getan haben, was ich nicht weiß, ob es wahr ist. Eine Drehung, die Sie vorgenommen haben, ist verlustfrei, wenn Sie genau denselben Bilddateicode wie vor dem Drehen und Speichern wiederherstellen können. Möglicherweise haben Sie nicht Recht, dass Sie wirklich eine verlustfreie Rotation durchgeführt haben. Wenn es wirklich verlustfrei war,

Timothy
quelle
-3

Die Gründe dafür sind einige

Die Art und Weise, wie Bilder codiert und komprimiert werden, ändert die Größe einfach aufgrund des Komprimierungsalgorithmus. Sie können dies testen, indem Sie es als Bitmap speichern und dann drehen. In diesem Format oder einem anderen Rohformat sollte die Größe gleich bleiben. Wenn dies nicht der Fall ist, fügt das Programm, das das Bild speichert, möglicherweise einige Metadaten oder etwas Neues hinzu.

Aber warum drehen Sie ein JPEG 20mal?

Cc Dd
quelle
2
Wenn Sie den Link in der ursprünglichen Frage lesen, zumindest für Windows Picture Viewer , und wenn die Abmessungen eines JPEG ein Vielfaches von 8 sind, sind Rotationen von JPEGS in WPV verlustfreie Transformationen. Eine einfache Möglichkeit, dies zu testen, besteht darin, viermal zu drehen (was zu derselben Ausrichtung wie das Original führt) und eine einfache pixelweise Bildsubtraktion durchzuführen.
Scottbb
@ scottbb Dies ist nicht unbedingt nur ein Problem mit Windows Picture Viewer. Alles, was ein verlustbehaftetes Format dreht, muss die Komprimierung neu berechnen. Wenn Sie ein Bild in Vielfachen von 8 drehen, passt alles in 8-Bit-Wörter und wird möglicherweise nicht so komprimiert, dass Artefakte hinzugefügt werden. Dies basiert auf der Funktionsweise des Algorithmus und ist im verwendeten Programm implementiert.
Cc Dd
-3

Wegen der Funktionsweise der Komprimierung von Bildern . Bei allen Formaten wie PNG oder JPG bleibt die Dateigröße nach dem Drehen im Allgemeinen nicht erhalten.

Für den Kompressor ist das gedrehte Bild nur ein anderes Bild. Aufgrund der Funktionsweise der Kompressionsheuristik kann nicht garantiert werden, dass ein gedrehtes Bild gleich komprimiert wird .

Natürlich, wenn die Komprimierung verlustfrei ist, wenn Sie das Bild 4-mal drehen, ist das Bild wieder dasselbe (gedreht, bis es wie das Original gekippt wird): In diesem Fall sollte es wieder dieselbe komprimierte Größe haben, wenn nicht Das liegt an einem der folgenden Gründe :

  • Metadaten hinzugefügt: Das Programm hat aus irgendeinem Grund Text hinzugefügt
  • Compressor changed: Das Programm speichert das Bild möglicherweise nur als Original neu, wenn keine Änderungen vorgenommen wurden. Wenn Sie jedoch Änderungen vornehmen (sogar 4 Umdrehungen um 90 Grad), wird das Bild möglicherweise erneut komprimiert Kompressor (das Programm weiß nicht mehr, dass es immer noch dasselbe Bild ist).
  • Im Allgemeinen liefert derselbe Kompressor (libPNG oder libJPG) sehr unterschiedliche Ergebnisse in verschiedenen Implementierungen, verschiedenen Versionen derselben Bibliothek und mit unterschiedlichen Kompressionsparametern (auch Betriebssystem und Compiler machen hier manchmal einen Unterschied).

Die Bildkomprimierung erfolgt durch Komprimieren von Bildern in 4x4-Stücke oder Stücke anderer Größe. Im Allgemeinen sieht ein Kompressor ein gedrehtes Bild als ein anderes Bild. Da es sich bei einem komprimierten Pixelblock jedoch um eine lineare Zerlegung handelt, ist es möglich, die linearen Zerlegungsmatrizen nur zu transponieren / spiegeln, wobei die linearen Zerlegungsmatrizen effektiv beibehalten werden Qualität:

Beachten Sie, dass dies auf Feature-Basis implementiert werden muss. Dies erklärt auch die anfängliche Vergrößerung. => Bei der ersten Drehung wird nur versucht, das Bild in drehbare Abschnitte zu komprimieren:

  • Andernfalls verschlechtert sich die Bildqualität
  • Wenn es erfolgreich ist, wird die Größe nur einmal erhöht, und jede Umdrehung behält die gleiche Qualität.

  • Diese Operation ist nur dann erfolgreich, wenn das Bild aus gleichen Teilen besteht. (Bildgröße ist ein Vielfaches der Größe des Blocks).

Die scottbb Antwort ist falsch und Sie können einen einfachen Test machen:

  • Öffnen Sie das Originalbild: Screenshot it
  • Drehe das Bild 4 mal mit WPV: Screenshot it
  • Vergleichen Sie die beiden Screenshots

Das Bild wird geändert (es wird beim ersten Drehen erneut komprimiert). Diese Änderung ist jedoch zeitlich begrenzt. Sie können sie jetzt ohne Qualitätsverlust erneut drehen (wenn das Bild ein Vielfaches von 8 hat).

Um direkt auf OP zu antworten:

Ich weiß, es dreht sich verlustfrei

Nicht, dass es sich nicht verlustfrei dreht, es verliert mindestens einmal an Qualität (bei der ersten Drehung: weil es es zuerst in einer Weise komprimieren sollte, die gedreht werden kann), dann behält es seine Qualität bei.

Spielentwickler
quelle
1
Bei der Frage geht es um verlustfreie Rotation, sodass eine erneute Komprimierung vermieden wird.
Agent_L
5
OP fragte nicht nach dem allgemeinen Fall, sondern genau nach dem einen Stück spezifischer Software und dem einen spezifischen Fall, der dies tut. Ihre Antwort ist nicht falsch, sie beantwortet nur eine andere Frage als die, die OP gestellt hat.
Agent_L
1
Bei den ersten drei Sätzen handelt es sich immer noch um eine andere Frage: "Wie funktioniert die Komprimierung von Bildern?" - bei verlustfreier Drehung erfolgt keine Komprimierung. "Zum Kompressor das gedrehte Bild" - wieder wird der Kompressor nicht aufgerufen. "Wenn die Komprimierung verlustfrei ist" - Die Komprimierung ist verlustbehaftet. Die Rotation ist verlustfrei. Nun, so weit bin ich bereit, dieses Argument anzunehmen. Ich kann Ihren Standpunkt sehen, dem stimme ich zu, aber es ist hier völlig fehl am Platz. Übrigens, ich bin auch ein Programmierer und habe meinen Teil zum Lesen und Schreiben von Rohdateien beigetragen.
Agent_L
1
Ich habe ein Bild in Paint erstellt, es viermal gedreht und es ist identisch, aber die Größe ist trotzdem von 1,6 auf 8,1 KB gestiegen. Binäres Diff zeigt, dass Bilddaten unberührt waren, es ist nur ein riesiger Teil der Metadaten in <?xpacketTags.
Agent_L
1
Wenn die Abmessungen eines JPEGs gleichmäßig durch 8 (oder 16 mit Unterabtastung) teilbar sind, kann es verlustfrei in Schritten von 90 Grad gedreht werden . Der Schlüssel ist, es nicht vollständig zu RGB zu decodieren, sondern direkt mit den DCT-Koeffizienten zu arbeiten. Es ist eine spezielle Funktion, die in einem allgemeinen Bildeditor nicht oft enthalten ist. Siehe zum Beispiel en.wikipedia.org/wiki/Libjpeg#jpegtran . Wenn Sie Ihr Experiment mit Windows Photo Viewer wie in der Frage angegeben durchgeführt haben, werden Sie feststellen, dass es tatsächlich verlustfrei ist.
Mark Ransom