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:
Und das Ergebnis:
Dann habe ich das Bild mit den Standardeinstellungen als JPEG gespeichert:
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 -l
von 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 APP0
Segment unangetastet, fügt dem Kommentar aber merkwürdigerweise ein Null-Byte hinzu (so dass es nullterminiert ist).
WPV fügt zwei APP1
Segmente 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:
Hier ist das Ergebnis:
Ich habe die Datei mit den folgenden Einstellungen als JPEG exportiert:
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: AC
Tabelle 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):
GIMP (Linux): 2.8.14 (aus Paket gimp
, Version 2.8.14-1+deb8u1
)
Window Photo Viewer (gemäß Bildmetadaten):
Microsoft Windows Photo Viewer 10.0.10586.0