Sono andato avanti e ho ripetuto l'esperimento per vedere se potevo capire cosa stava succedendo.
Procedura
Ho generato un'immagine RGB casuale da 256 per 256 pixel utilizzando il filtro "Rumore solido" in GIMP (Filtri> Rendering> Nuvole> Rumore solido ...) utilizzando le impostazioni predefinite (mostrate di seguito):
E il risultato:
Quindi ho salvato l'immagine come JPEG usando le impostazioni predefinite:
Quindi ho trasferito l'immagine su Windows e ho aperto l'immagine con Windows Photo Viewer facendo clic con il tasto destro sull'immagine in Esplora file e scegliendo Anteprima dal menu. Quindi ho ruotato l'immagine usando i pulsanti in basso e ho salvato l'immagine passando all'immagine successiva usando i tasti freccia.
Per ciascuno dei test seguenti ho iniziato con una copia dell'immagine originale e ruotato (facendo clic sul pulsante di rotazione) il numero corrispondente di volte prima di salvare. Ecco le dimensioni corrispondenti ( 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
Osservazioni immediate
- Windows Photo Viewer (WPV) aumenta notevolmente le dimensioni; la quantità di aumento è di circa quattro volte in questo test!
- Tutte le nuove immagini aumentano circa della stessa dimensione, ma non sono identiche.
- Il WPV non ricodifica né salva nuovamente l'immagine quando viene ruotata di un multiplo di 360 gradi. (Il timestamp, 11:27, è quando i file sono stati copiati per la prima volta.)
L'utilizzo cmp -l
su file che dovrebbero avere un contenuto identico ci consente di vedere dove differiscono i file.
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
Questi file differiscono in soli quattro byte (in realtà in un timestamp), il che significa che WPV fa sempre la stessa cosa; ora dobbiamo solo capire di cosa si tratta.
Osservazioni dettagliate
Per questo ho usato JPEGsnoop per vedere cosa fosse esattamente nelle immagini.
Dal momento che le uscite sono piuttosto lunghe, le ho collegate come sostanza . Ecco un riepilogo delle differenze:
GIMP utilizza solo un segmento APP0
(JFIF) e COM
(commento) per i metadati. WPV lascia il APP0
segmento intatto, ma stranamente aggiunge un byte nullo al commento (in modo che sia nullo).
WPV aggiunge due APP1
segmenti, che sono metadati Exif e XMP. Questi segmenti sono rispettivamente 4286 e 12726 byte. Insieme rappresentano quasi l'intero aumento della dimensione dei file.
GIMP produce un JPEG progressivo, mentre WPV produce un JPEG di base (non progressivo). Per questo motivo l'immagine di GIMP ha più segmenti di scansione, mentre l'immagine WPV ne ha solo uno. Nella mia esperienza, l'immagine progressiva a volte è leggermente più piccola.
GIMP ha usato il sottocampionamento cromatico 1 × 1, mentre WPV ha usato il sottocampionamento 2 × 2. Questo mi porta a credere che WPV non stia usando una rotazione "vera" senza perdita, a meno che non sia in qualche modo in grado di rilevare questa immagine in bianco e nero.
Per risolvere questi problemi, ho eseguito un secondo test.
Procedura
Ho seguito passaggi simili al primo test. Ho creato un'immagine RGB 256 × 256 casuale usando il filtro Rumore RGB (Filtri> Naso> Naso RGB ...) con le seguenti impostazioni:
Ecco il risultato:
Ho esportato il file come JPEG utilizzando le seguenti impostazioni:
Progressivo è stato disattivato, ma il sottocampionamento è ancora impostato su 4: 4: 4 (che è un altro nome per il sottocampionamento 1 × 1). La qualità è aumentata a 98.
Ho copiato l'immagine e ruotato la copia in senso orario; quindi copiato la versione ruotata e ruotata quella copia in senso antiorario, in modo da poter confrontare direttamente la qualità tra l'originale e la copia elaborata da WPV.
risultati
-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
Sebbene l'aumento questa volta sia minore in termini relativi (circa il 40%), l'aumento assoluto è ancora maggiore: circa 62 kB. Ciò suggerisce che WMV sta utilizzando una codifica meno efficiente.
Userò ImageMagick per confrontare le due immagini:
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
Vi sono zero pixel diversi tra la copia originale e quella ruotata. Quindi, anche se WPV non utilizza una rotazione senza perdita "vera", sta facendo un lavoro abbastanza buono. Sospetto di sapere cosa stia succedendo e per spiegare mi sposterò un po 'nella matematica dietro la compressione JPEG.
L'algoritmo di compressione JPEG suddivide un'immagine in blocchi di 8 × 8 pixel. Ciascuno di questi blocchi viene quindi sottoposto a una trasformazione discreta del coseno (DCT) . I coefficienti DCT risultanti descrivono il blocco come una somma di onde a frequenza diversa. L'algoritmo quindi "getta via" alcune informazioni nelle onde ad alta frequenza che corrispondono al rumore e ai dettagli molto piccoli. Il processo di decodifica inverte il DCT, sommando le onde memorizzate per ripristinare il blocco.
È possibile ruotare le "onde" DCT senza effettivamente annullare e ripetere la trasformazione (in pratica si trasformano tutte le onde orizzontali in onde verticali e viceversa). Ciò che penso accada in WPV è che l'immagine viene effettivamente decodificata, ruotata e quindi ricodificata. Durante il processo di ricodifica, poiché la dimensione della nostra immagine è un multiplo di 8 in entrambe le dimensioni, ciascuno dei nuovi blocchi corrisponde a uno dei blocchi originali. È importante sottolineare che, poiché ogni blocco non ha componenti ad alta frequenza, l'algoritmo non elimina alcuna informazione e trova esattamente i componenti DCT giusti che avrebbe una rotazione "vera" senza perdita.
Infine, esaminerò di nuovo i componenti dei file JPEG. I risultati vengono nuovamente collegati come sintesi . Confrontando i due:
L'immagine WPV contiene 4286 + 2 byte extra di metadati Exif, 1 byte extra nel commento e 12.726 + 2 byte di metadati XMP. Questo è un totale di 17.017 byte di metadati aggiuntivi. A cosa servono tutti quei dati? Ho scrutato il file con il mio fidato editor esadecimale e una copia degli standard pertinenti:
I metadati Exif sono strutturati come un'immagine TIFF, che contiene una serie di tag (c'è molta più complessità, ma la salterò sopra). La maggior parte dei byte nel segmento Exif sono contenuti in due tag identici con numero di tag EA1C
(59.932 decimale). Quel numero di tag non è documentato da nessuna parte che ho potuto trovare. Entrambi i tag contengono 2060 byte di tipo "non definito", che sono tutti byte null tranne i primi sei ( 1C EA 00 00 00 08
). Non ho idea di cosa siano questi tag, perché ce ne siano due e perché debbano essere di 2 kB ciascuno.
I metadati XMP sono in realtà un intero documento XML incorporato con spazio dei nomi e UUID lunghi, che contiene solo la stringa della versione WPV (che era già nei metadati Exif). Tuttavia, ciò rappresenta solo circa 400 byte. Il resto del segmento è 122 ripetizioni di 100 spazi seguiti da una nuova riga . Sono oltre 12.000 byte di spazio totalmente sprecato.
Come il test precedente, sia GIMP che WPV utilizzano le stesse tabelle di quantizzazione DCT. Ciò significa che dovrebbero calcolare esattamente gli stessi coefficienti DCT, motivo per cui le immagini sono esattamente le stesse. Non sono sicuro se WPV stia utilizzando le stesse tabelle di quantizzazione o se copi le tabelle dall'input.
A differenza del test precedente, questa volta WPV utilizza il sottocampionamento 1 × 1, quindi potrebbe effettivamente rilevare che si tratta di un'immagine a colori (o almeno che sono necessari campioni più alti per ricodificare senza perdita di immagine).
GIMP e WPV utilizzano diverse tabelle Huffman (parte della fase di codifica dell'entropia). Le tabelle per WPV sono più grandi di un totale di 279 byte e in un caso contengono 7 volte più codici.
Osservando le statistiche di JPEGsnoop, possiamo vedere che alcuni di questi codici sono usati raramente. Ad esempio, nella ID: 1, Class: AC
tabella, dei 119 codici a 16 bit definiti, solo 23 sono effettivamente utilizzati. Nel complesso, il segmento di scansione effettivo è maggiore del 28,5% nella versione WPV.
Sommario
Il WPV potrebbe non fare rotazioni "vere" senza perdita, ma le rotazioni sembrano essere praticamente senza perdita.
Le dimensioni extra sono in parte dovute a una quantità fissa di metadati aggiunti e in parte a una codifica entropica meno efficiente.
Informazioni sulla versione:
OS (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
Sistema operativo (Windows):
GIMP (Linux): 2.8.14 (dal pacchetto gimp
, versione 2.8.14-1+deb8u1
)
Window Photo Viewer (secondo i metadati delle immagini):
Microsoft Windows Photo Viewer 10.0.10586.0