Ik ging door en herhaalde het experiment om te zien of ik erachter kon komen wat er aan de hand was.
Procedure
Ik heb een willekeurige RGB-afbeelding van 256 bij 256 pixels gegenereerd met de "Solid Noise" -filter in GIMP (Filters> Render> Clouds> Solid Noise ...) met behulp van de standaardinstellingen (hieronder weergegeven):
En het resultaat:
Vervolgens heb ik de afbeelding als JPEG opgeslagen met de standaardinstellingen:
Daarna heb ik de afbeelding naar Windows en opende de afbeelding met Windows Photo Viewer door met de rechtermuisknop op de afbeelding in de Verkenner te klikken en Voorbeeld te kiezen in het menu. Vervolgens heb ik de afbeelding geroteerd met de knoppen onderaan en de afbeelding opgeslagen door met de pijltjestoetsen naar de volgende afbeelding te navigeren.
Voor elk van de onderstaande tests begon ik met een kopie van de originele afbeelding, en het overeenkomstige aantal keren geroteerd (geklikt op de rotatieknop) voordat het werd opgeslagen. Hier zijn de reslting-formaten ( ls -l -r
):
grootte in bytes datum laatste wijziging VVVVV VVVVV-rwxrwx --- 1 root vboxsf 6258 8 nov 11:24 original.jpg-rwxrwx --- 1 root vboxsf 23645 8 november 11:30 cw.jpg-rwxrwx --- 1 root vboxsf 23636 8 november 11:30 cw-cw.jpg-rwxrwx --- 1 root vboxsf 23649 8 nov 11:30 cw-cw-cw.jpg-rwxrwx --- 1 root vboxsf 6258 8 nov 11:27 cw-cw-cw-cw.jpg-rwxrwx --- 1 root vboxsf 23649 8 nov 11:31 cw-cw-cw-cw-cw.jpg-rwxrwx --- 1 root vboxsf 23649 8 november 11:29 ccw.jpg-rwxrwx --- 1 root vboxsf 23636 8 november 11:29 ccw-ccw.jpg-rwxrwx- - 1 root vboxsf 23645 8 november 11:29 ccw-ccw-ccw.jpg-rwxrwx --- 1 root vboxsf 6258 8 november 11:27 ccw-ccw-ccw-ccw.jpg-rwxrwx --- 1 root vboxsf 23649 8 nov 11:30 ccw-ccw-ccw-ccw-ccw.jpg
Onmiddellijke waarnemingen
- Windows Photo Viewer (WPV) vergroot de grootte drastisch ; de toename is ongeveer vier keer in deze test!
- Alle nieuwe afbeeldingen worden groter tot ongeveer dezelfde grootte, maar ze zijn niet identiek.
- WPV hercodeert de afbeelding niet en slaat deze zelfs niet opnieuw op wanneer deze wordt gedraaid met een veelvoud van 360 graden. (Het tijdstempel, 11:27, is wanneer de bestanden voor het eerst werden gekopieerd.)
Door cmp -l
te gebruiken op bestanden die identieke inhoud zouden moeten hebben, kunnen we zien waar de bestanden verschillen.
robert @ unit ../jpeg-rotate-test% cmp -l cw.jpg ccw-ccw-ccw.jpg 2223 63 62 2224 60 71 2226 60 64 2227 60 66robert @ eenheid ../jpeg-rotate-test% cmp -l cw-cw.jpg ccw-ccw.jpg 2223 63 62 2224 60 71 2226 60 64 2227 62 64robert @ eenheid ..jpeg-rotate-test% cmp - l ccw.jpg cw-cw-cw.jpg 2223 62 63 2224 71 60 2226 64 60 2227 61 64 robert @ unit ../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 @ eenheid ../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
Deze bestanden verschillen in slechts vier bytes (eigenlijk in een tijdstempel), wat betekent dat WPV elke keer hetzelfde doet; nu hoeven we alleen maar uit te zoeken wat dat is.
Gedetailleerde observaties
Hiervoor heb ik JPEGsnoop gebruikt om te zien wat er precies in de afbeeldingen stond.
Aangezien de outputs vrij lang zijn, heb ik er in eerste instantie aan gelinkt. Hier is een samenvatting van de verschillen:
-
GIMP gebruikt alleen een APP0
(JFIF) en COM
(commentaar) -segment voor metadata . WPV laat het APP0
-segment onaangeroerd, maar voegt merkwaardig genoeg een null-byte toe aan de opmerking (zodat deze wordt beëindigd met null).
-
WPV voegt er twee toe APP1
-segmenten, dit zijn Exif- en XMP-metadata. Deze segmenten zijn respectievelijk 4286 en 12726 bytes. Samen zijn ze verantwoordelijk voor bijna de gehele toename in bestandsgrootte.
-
GIMP produceert een progressieve JPEG, terwijl WPV een basislijn (niet-progressieve) JPEG produceert. Om deze reden heeft de afbeelding van GIMP meerdere scansegmenten, terwijl de WPV-afbeelding er maar één heeft. In mijn ervaring is het progressieve beeld soms iets kleiner.
-
GIMP gebruikte 1 × 1 chroma subsampling, terwijl WPV 2 × 2 subsampling gebruikte. Dit doet me geloven dat WPV geen "echte" verliesloze rotatie gebruikt, tenzij het op de een of andere manier kan detecteren dat dit een zwart-witafbeelding is.
Oplossen deze problemen heb ik een tweede test uitgevoerd.
Procedure
Ik volgde dezelfde stappen als bij de eerste test. Ik heb een willekeurige 256 × 256 RGB-afbeelding gemaakt met behulp van het RGB-ruisfilter (Filters> Neus> RGB-neus ...) met de volgende instellingen:
Hier is de resultaat:
Ik heb het bestand geëxporteerd als JPEG met de volgende instellingen:
Progressive is uitgeschakeld, maar Subsampling is nog steeds ingesteld op 4: 4: 4 (wat een andere naam is voor 1 × 1 subsampling). De kwaliteit is verhoogd naar 98.
Ik heb de afbeelding gekopieerd en de kopie met de klok mee gedraaid; vervolgens de geroteerde versie gekopieerd en die kopie tegen de klok in gedraaid, zodat we de kwaliteit rechtstreeks kunnen vergelijken tussen het origineel en de door WPV verwerkte kopie.
Resultaten
-rwxrwx-- - 1 root vboxsf 159774 8 november 16:21 original-random.jpg-rwxrwx --- 1 root vboxsf 222404 8 november 16:24 cw-random.jpg-rwxrwx --- 1 root vboxsf 222467 8 november 16:24 cw- ccw-random.jpg
Hoewel de toename deze tijd relatief kleiner is (ongeveer 40%), is de absolute toename zelfs nog groter - ongeveer 62 kB. Dit suggereert dat WMV een minder efficiënte codering gebruikt.
Ik gebruik ImageMagick om de twee afbeeldingen te vergelijken:
robert @ unit. ./jpeg-rotate-test% vergelijk -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 Afbeelding: origineel-willekeurig.jpg Kanaalvervorming: AE rood: 0 groen: 0 blauw: 0 alle: 0 origineel-willekeurig. jpg = > JPEG 256x256 256x256 + 0 + 0 8-bit sRGB 0.050u 0: 00.020
Er zijn nul pixels verschillend tussen de originele en de geroteerde kopie. Dus zelfs als WPV geen gebruik maakt van "echte" verliesloze rotatie, doet het zijn werk goed genoeg. Ik vermoed dat ik weet wat er aan de hand is, en om het uit te leggen, ga ik een beetje in op de wiskunde achter JPEG-compressie.
Het JPEG-compressie-algoritme splitst een afbeelding op in blokken van 8 × 8 pixel. Elk van deze blokken wordt vervolgens onderworpen aan een Discrete Cosine Transform (DCT). De resulterende DCT-coëfficiënten beschrijven het blok als een som van golven met verschillende frequentie. Het algoritme "gooit" wat informatie weg in de hoogfrequente golven die corresponderen met ruis en zeer kleine details. Het decoderingsproces keert de DCT om, waarbij de opgeslagen golven bij elkaar worden opgeteld om het blok terug te krijgen.
Het is mogelijk om de DCT "golven" te roteren zonder de transformatie daadwerkelijk ongedaan te maken en opnieuw uit te voeren (in feite draai je alle horizontale golven in verticale golven en vice versa). Wat ik denk dat er in WPV gebeurt, is dat de afbeelding daadwerkelijk wordt gedecodeerd, geroteerd en vervolgens opnieuw wordt gecodeerd. Omdat tijdens het hercoderingsproces de grootte van onze afbeelding een veelvoud is van 8 in beide dimensies, komt elk van de nieuwe blokken overeen met een van de originele blokken. Belangrijk is dat aangezien elk blok geen hoogfrequente componenten heeft, het algoritme geen informatie weggooit en precies de juiste DCT-componenten vindt die een "echte" verliesloze rotatie zou hebben.
Ten slotte, ik ' Ik kijk nogmaals naar de componenten van de JPEG-bestanden. De resultaten zijn weer gelinkt als gists. Vergelijking van de twee:
-
De WPV-afbeelding bevat 4286 + 2 bytes Exif-metadata extra, 1 extra byte in de opmerking en 12,726 + 2 bytes XMP-metadata. Dit is in totaal 17.017 bytes aan extra metadata. Waar worden al die gegevens voor gebruikt? Ik gluurde in het bestand met mijn vertrouwde hex-editor en een kopie van de relevante standaarden:
-
Exif-metagegevens zijn gestructureerd als een TIFF-afbeelding, die een aantal tags bevat (er is manier meer complexiteit, maar ik zal het meteen overslaan). De meeste bytes in het Exif-segment bevinden zich in twee identieke tags met tagnummer EA1C
(59.932 decimaal). Dat tagnummer is nergens gedocumenteerd dat ik kon vinden. Beide tags bevatten 2060 bytes van het type "ongedefinieerd", die allemaal nul bytes zijn, behalve de eerste zes ( 1C EA 00 00 00 08
). Ik heb geen idee wat deze tags zijn, waarom er twee zijn en waarom ze elk 2 kB moeten zijn.
-
De XMP-metadata is eigenlijk een volledig ingesloten XML-document met naamruimte en lange UUID's, die alleen de WPV-versiestring bevat (die al in de Exif-metadata stond). Dat is echter slechts goed voor ongeveer 400 bytes. De rest van het segment is 122 herhalingen van 100 spaties gevolgd door een nieuwe regel . Dat is meer dan 12.000 bytes aan totaal verspilde ruimte.
-
Net als de vorige test gebruiken zowel GIMP als WPV dezelfde DCT-kwantisatietabellen. Dit betekent dat ze exact dezelfde DCT-coëfficiënten moeten berekenen, en daarom zijn de afbeeldingen precies hetzelfde. Ik weet niet zeker of WPV toevallig dezelfde kwantisatietabellen gebruikt of dat het de tabellen van de invoer kopieert.
-
In tegenstelling tot de vorige test gebruikt WPV dit keer 1 × 1 subsampling, dus het kan in feite detecteren dat dit een kleurenafbeelding is (of in ieder geval dat hogere samples nodig zijn om de afbeelding zonder verlies opnieuw te coderen).
-
GIMP en WPV gebruiken verschillende Huffman-tabellen (onderdeel van de entropiecodeerstap). De tabellen voor WPV zijn groter met in totaal 279 bytes en bevatten in één geval 7 keer zoveel codes.
Als we naar de statistieken van JPEGsnoop kijken, kunnen we zien dat sommige van deze codes zelden worden gebruikt. In de ID: 1, Class: AC
-tabel, van de 119 gedefinieerde 16-bits codes, worden er bijvoorbeeld slechts 23 daadwerkelijk gebruikt. Over het algemeen is het daadwerkelijke scansegment 28,5% groter in de WPV-versie.
Samenvatting
-
WPV doet het misschien niet " echte "verliesloze rotaties, maar de rotaties lijken praktisch verliesloos te zijn.
-
De extra grootte is gedeeltelijk te wijten aan een vaste hoeveelheid toegevoegde metadata, en gedeeltelijk aan minder efficiënte entropiecodering .
Versie-informatie:
-
OS (Linux) ( uname -a
):
Linux-eenheid 3.16.0-4-amd64 # 1 SMP Debian 3.16.36-1 + deb8u1 (2016-09-03) x86_64 GNU / Linux
-
OS (Windows):
-
GIMP (Linux): 2.8.14 (uit pakket gimp
, versie 2.8.14-1 + deb8u1
)
-
Window Photo Viewer (volgens metadata van afbeeldingen):
Microsoft Windows Photo Viewer 10.0.10586.0