Vraag:
Als een afbeelding zonder verlies wordt geroteerd, waarom verandert de bestandsgrootte dan?
oscilatingcretin
2016-11-07 06:11:00 UTC
view on stackexchange narkive permalink

Ik was op zoek naar methoden voor beeldrotatie zonder verlies en stuitte op deze vraag die het nogal mooi verklaart:

Zijn rotaties van "Windows Photo Viewer" verliesloos?

Dus heb ik een 256 × 256 JPEG gemaakt met willekeurige pixels (Photoshop-wolkenfilter) en deze vervolgens geroteerd met Windows Picture Viewer. Na rotatie is de bestandsgrootte zelfs toegenomen, maar alleen bij de eerste rotatie. Elke volgende rotatie daarna bleef de bestandsgrootte statisch. Ik weet dat het verliesloos roteert, omdat ik het meerdere keren heb geroteerd zonder merkbaar kwaliteitsverlies, terwijl een beeld van 257 × 257 dat 20 keer werd geroteerd, erg verliesgevend werd.

Met hoeveel is de bestandsgrootte toegenomen tijdens uw tests?
@JamesSnell Ik wist dat ik dat had moeten opnemen. Degene die ik net deed met het filter voor verschilklanken van GIMP was oorspronkelijk 14.583 bytes, maar veranderde na roation in 23.638 bytes. Dat is een verschil van meer dan 9000 bytes, wat veel extra gegevens lijkt als we het alleen over metadata hebben.
@JamesSnell Dus ik herhaalde dezelfde test met een 512x512 afbeelding en het bestandsverschil is 9.612 bytes (het was 9.055 met de eerste). Omdat de grotere bestandsgrootte niet in verhouding stond tot de toename in afmetingen, denk ik dat het veilig is om te zeggen dat het inderdaad metadata zijn
Dat lijkt veel extra metadata. Ik zou niet te snel aannemen dat al die aanvullende gegevens metadata zijn. Het lijkt mij dat het verschil in grootte als gevolg van metadata bijna een constante zou moeten zijn (tot binnen een paar bytes om rekening te houden met de tekenreeksweergave van sommige getallen).
Wanneer u aanvullende informatie verstrekt die relevant is voor de vraag, moet u deze in de vraag bewerken in plaats van in de opmerkingen. Opmerkingen zijn kortstondig en kunnen van tijd tot tijd worden opgeschoond.
Wat gebeurt er als je roteert met een andere (betere) tool voor beeldmanipulatie? Heck, het zou me niet verbazen als WPV de originele pixels zou opslaan :-(
Het zou handig zijn om de originele versie van uw testafbeelding te uploaden.
@CodesInChaos - een 'voor en na' set bestanden zou ons in staat stellen de vraag volledig te beantwoorden. Maar ze moeten worden geleverd op een manier die ze niet verandert, dus niet de gebruikelijke imgur enz. Route.
Zou het niet zo kunnen zijn dat Windows Picture Viewer de foto opnieuw heeft opgeslagen met een kleinere compressieverhouding?
Het punt si tha WPV comprimeert het beeld opnieuw bij de eerste rotatie, maar het comprimeert het op een manier dat als de grootte een veelvoud is van 8 opeenvolgende rotaties kan worden gedaan door simpelweg bytetransformaties toe te passen op de gecomprimeerde bytestream, mijn antwoord correct adres dat, zelfs als het downvotet is, heeft het de volledige uitleg (en het is eigenlijk het enige juiste antwoord)
Als @DarioOO, maar probeer het duidelijk te maken. * Losslessly * betekent niet gelijk of idempotent. Door een jpg opnieuw te coderen, zou men een betere compressie kunnen hebben (computer met beter algoritme / geheugen versus camera), en dit is waar met of zonder rotatie. * Losslessly * betekent alleen dat de niet-gecomprimeerde afbeelding hetzelfde zal zijn, niets over de originele (gecomprimeerde) afbeelding.
@GiacomoCatenazzi Theoretisch gezien heb je gelijk, maar in de praktijk maakt JPEG-compressie dit bijna onmogelijk. De verliesloze JPEG-rotatie van 90 graden gebeurt precies zonder compressie, via transpositie van gecomprimeerde gegevens. Zoals ik uw opmerking begrijp, zegt u dat er altijd hercompressie is, gewoon niet te onderscheiden, terwijl DarioOO zegt dat er alleen een initiële hercompressie is in een transponeerbaar formaat en dat het vanaf dat moment wordt omgezet. Ik geloof dat MCU-uitgelijnde JPEG direct uit de doos kan worden getransponeerd. http://www.betterjpeg.com/lossless-rotation.htm
MS-compressiebibliotheken zijn slecht en leveren vaak minder compressie op dan andere engines die "hetzelfde" algoritme gebruiken.
Acht antwoorden:
Ilmari Karonen
2016-11-07 20:30:23 UTC
view on stackexchange narkive permalink

Dit wordt hoogstwaarschijnlijk veroorzaakt door entropiecodering, de laatste fase zonder verlies van JPEG-compressie, nadat de beeldgegevens zijn gekwantiseerd om de grootte te verkleinen.

Wanneer een JPEG-afbeelding wordt verliesloos geroteerd, deze laatste verliesvrije coderingslaag moet ongedaan worden gemaakt, de uitgepakte DCT-coëfficiënten worden door elkaar geschud en vervolgens moeten de geschudde coëfficiënten opnieuw entropie worden gecodeerd. Aangezien de efficiëntie van de entropiecoderingslaag afhangt van de volgorde van de DCT-coëfficiënten binnen elk blok, waardoor het roteren van de afbeelding zal veranderen, zou het niet moeten verbazen dat het geroteerde afbeeldingsbestand een paar procent kleiner of groter kan zijn dan het origineel. / p>

Er zijn ook verschillende manieren waarop de entropiecoderingsstap kan worden uitgevoerd, dus het is heel goed mogelijk dat de bestandsgrootte van exact dezelfde JPEG-afbeelding kan variëren afhankelijk van de software die de codering uitvoert. Enkele van de mogelijke verschillen tussen encoders zijn:

  • keuze van rekenkundige codering (zeldzaam maar potentieel efficiënter, vroeger gepatenteerd) versus Huffman-codering (eenvoudiger, standaard);
  • keuze van sequentiële (elk 8x8 pixelblok wordt één voor één gecodeerd) versus progressief (lage frequentiecomponenten van alle blokken worden gecodeerd vóór de hogere frequentiecomponenten, meestal iets compacter) coderingsvolgorde;
  • keuze voor het gebruik van de standaard Huffman-symbooltabellen (sneller, eenvoudiger, kan efficiënter zijn voor zeer kleine afbeeldingen) vs. aangepaste tabellen die zijn geoptimaliseerd voor elke afbeelding (meestal efficiënter voor grote afbeeldingen, langzamer en complexer om te coderen);
  • als aangepaste Huffman-tabellen worden gebruikt, kunnen verschillende encoders mogelijk verschillende tabellen genereren voor dezelfde afbeeldingsgegevens;
  • verschillende details op laag niveau van het coderingsproces zelf, zoals of en wanneer herstartmarkeringen moeten worden opgenomen in de datastroom, kan ook variëren tussen encoders.

Bovendien bevatten de "JPEG-bestanden" waarmee mensen normaal gesproken werken, JPEG-gecomprimeerde afbeeldingsgegevens verpakt in een JFIF of een Exif -container, die de afbeeldingsgegevens combineert met een of meer metadatablokken, en introduceert zijn eigen set complicaties. Zelfs als de software die de afbeelding roteert eigenlijk geen substantiële wijzigingen aanbrengt in de JFIF / Exif-metadata, kan het eenvoudigweg herschikken van de gegevens de bestandsgrootte mogelijk met enkele bytes beïnvloeden.

In het bijzonder de JFIF / Exif-metagegevens kunnen een of meer miniaturen van de volledige afbeelding bevatten, en software die afbeeldingen roteert, zou de miniaturen echt moeten regenereren (of ook zonder verlies draaien!) Zodat ze overeenkomen met de nieuwe oriëntatie van de volledige afbeelding. -formaat afbeelding. Dit alleen al zou gemakkelijk het waargenomen verschil in grootte kunnen verklaren.

Voor een verschil van 9 KB (60%) zouden miniaturen zijn.
JPEG is misschien te eenvoudig om dit de moeite waard te maken als encoders, maar video-encoders zoals x264 kunnen in feite rekening houden met het vermogen van de entry-coder om te coderen wat ze vervolgens gaan uitvoeren, wanneer ze beslissingen nemen over snelheid versus vervorming. (d.w.z. beslissen hoeveel bits elk alternatief kan kosten, en dat afwegen tegen de verliesfout). Dit wordt trelliskwantisatie genoemd. Zie [Opmerkingen over de implementatie van trelliskwantisering in H.264] (http://akuvian.org/src/x264/trellis.txt) van de auteur van x264 (Loren Merritt); hij begint met een vrij eenvoudige uitleg van het doel.
Hoe dan ook, de JPEG-encoder heeft mogelijk DCT-coëfficiënten gekozen zodat ze goed comprimeerden met de entropie-coder, dus zelfs een optimale compressor kon een geroteerde versie niet zo klein maken. (Omdat ze in een andere volgorde zouden worden geplaatst, zouden ze waarschijnlijk minder goed comprimeren.) Dit zou vrijwel zeker een klein effect zijn voor JPEG, aangezien elk 8x8 blok afzonderlijk wordt gecodeerd (de toestand van de entropie-coder, AFAIK, resetten). (I-frames in h.264 gebruiken intra-voorspelling, voorspellen vanuit andere blokken in hetzelfde frame, waardoor ze kleiner zijn dan een JPEG met dezelfde visuele kwaliteit.)
2012rcampion
2016-11-09 00:43:04 UTC
view on stackexchange narkive permalink

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):

enter image description here

En het resultaat:

enter image description here

Vervolgens heb ik de afbeelding als JPEG opgeslagen met de standaardinstellingen:

enter image description here

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:

enter image description here

Hier is de resultaat:

enter image description here

Ik heb het bestand geëxporteerd als JPEG met de volgende instellingen:

enter image description here

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):

    enter image description here

  • GIMP (Linux): 2.8.14 (uit pakket gimp , versie 2.8.14-1 + deb8u1 )

    enter image description here

  • Window Photo Viewer (volgens metadata van afbeeldingen):

      Microsoft Windows Photo Viewer 10.0.10586.0  
scottbb
2016-11-07 07:04:00 UTC
view on stackexchange narkive permalink

BEWERKEN : dit antwoord werd gepost voordat ik wist dat de bestanden met ongeveer 9 KiB in omvang waren toegenomen (9055 bytes voor de 256 × 256 afbeelding, 9612 KiB voor de 512 × 512 afbeelding).

Naar alle waarschijnlijkheid heeft Windows Picture Viewer bij het draaien van de afbeelding een (of beide) van de volgende dingen gedaan:

  1. Toegevoegd een EXIF-tag die niet in de originele JPEG-afbeelding stond (misschien de Orientation-tag);
  2. Informatie gewijzigd / toegevoegd aan een tag die al bestond (misschien tags voor verwerkingssoftware of afbeeldingssoftware).
  3. Dit verhoogde de bestandsgrootte vanwege de extra EXIF-tag (en / of aanvullende gegevens naast bestaande tags).

    Latere rotaties hebben de bestandsgrootte niet vergroot omdat alle tags en / of taggegevens die WPV zou hebben toegevoegd / gewijzigd, waren er al. Alleen de Orientation Tag waarde is gewijzigd (en misschien ook de datum / tijd tag-waarden).


    EDIT : het is vrijwel zeker dat dit uitleg kan geen rekening houden met ongeveer 9 KiB aan extra gegevens in het bestand. Verder, bij afwezigheid van andere redenen voor de toename van de grootte, zou deze verklaring verwachten dat de toename in grootte min of meer constant zou zijn (modulo enkele lengteverschillen tussen stringrepresentaties van numerieke gegevens, waarschijnlijk een paar bytes) . Dat is duidelijk niet wat hier gebeurt, althans niet de volledige uitleg.

En een EXIF-tag neemt 9kB in beslag? Nou, dit is in ieder geval eenvoudig te testen - laat de OP EXIF ​​of andere tags van de geroteerde afbeelding verwijderen en kijk hoe de bestandsgrootte verandert.
@CarlWitthoft de 9kB is nieuwe informatie. Bewerken om dat te vermelden.
James Snell
2016-11-07 06:57:32 UTC
view on stackexchange narkive permalink

Zonder reverse engineering van de jpeg en / decoder is het onmogelijk met zekerheid te zeggen. Er zijn eigenlijk een aantal jpeg-standaarden en in tegenstelling tot wat vaak wordt gedacht, kunnen ze niet allemaal worden gewijzigd zonder opnieuw te coderen.

Het is mogelijk dat de eerste save een lossy herschrijving is in zijn favoriete jpeg-smaak en de daaropvolgende rotaties zijn een eenvoudige metadata-tweak of een bewerking rechtstreeks op de DCT-tabel (wat mogelijk is voor sommige coderingsschema's).

De toename in bestandsgrootte kan ook wat extra metadata bevatten, hoewel 9k veel lijkt, is het mogelijk. De toename kan ook worden verklaard door de toevoeging van een miniatuur die mogelijk niet aanwezig was in de uitvoer van GIMP. Mogelijk kunnen we meer informatie rechtstreeks uit de bestanden halen (vóór WPV en erna).

In elk geval is het proberen om zonder problemen met jpeg te werken echt een dwaze boodschap, aangezien het alleen nuttig is bij bepaalde afbeeldingsformaten, niet alle decoders en encoders zijn identiek en het vereist dat die editors rechtstreeks met de jpeg-inhoud werken, waarvan u niet kunt vertrouwen dat dit het geval is ... Alleen omdat dit nu het geval is, betekent niet dat dit in de toekomst zal blijven.

Je kunt beter met een verliesvrij formaat werken en de pijn volledig vermijden.

Ik ben er helemaal niet van overtuigd dat roterende jpeg-gegevens in de eerste plaats een hercodering moeten veroorzaken.
Het hangt ervan af of je een programmeur bent of niet ... Ik denk dat je dat niet bent. U zou specifiek naar die optimalisatie moeten zoeken om die minimale wijziging aan te brengen, anders zou een opslagbewerking starten vanaf de niet-gecomprimeerde bitmap.
Uit de gekoppelde vraag is het duidelijk dat Windows Photo Viewer JPEG-bestanden zonder verlies roteert.
Maar onder welke omstandigheden ... Dat is het deel dat we niet weten.
@James Ik ben geen programmeur op laag niveau, hoewel ik op tv speel :-). Het OP gaf een link naar een nauwkeurige beschrijving van wanneer er opnieuw gecodeerd zou worden en wanneer niet. Ik had uit die discussie afgeleid dat hij slechts $ \ frac {\ pi} {2} $ had gerouleerd. Ik ben het ermee eens dat willekeurige hoekrotatie hercodering veroorzaakt, en wat dat betreft informatieverlies zal veroorzaken tenzij het X-bij-Y-beeld is ingebed in een gebied dat minstens zo groot is als de hypotenusa.
Het gaat er niet om wat wiskundig haalbaar is. Het gaat er echter om wat de code eigenlijk doet. Wat het OP ziet, is dat iteratie 1 een verandering in de bestandsgrootte veroorzaakt, maar latere iteraties niet. Daar zijn redenen voor en ik zal zo een bewerking uitvoeren om uit te leggen wat er kan gebeuren.
De oorzaak van de verliesloze rotatie (wat een slechte term is; beter zou _omkeerbaar_ zijn) is wanneer de afmetingen van de afbeelding veelvouden zijn van 8 of 16, wat de _Minimum Compressible Unit_ is. Als een JPEG geen gedeeltelijke MCU's bevat, kan deze worden geroteerd / omgedraaid zonder enige wijziging aan de DCT-datablokken. In dat geval is er helemaal geen hercodering, alleen het wijzigen van een matrix van indexen naar die blokken.
@scottbb - dat is alleen van toepassing op bepaalde coderingsmethoden binnen de jpeg-specificatie. en het is afhankelijk van de software die op zoek is naar die optimalisatie. Alles wat we weten is (a) ja, het is mogelijk onder bepaalde omstandigheden en (b) dat we niet precies weten wat * deze * applicatie doet ...
We zijn er vrij zeker van dat we weten _dat_ WPV omkeerbaar roteert voor afbeeldingen met afmetingen veelvouden van 8/16. Zie de opmerking van @Tristan's op het antwoord van Matt Grum op de vraag waarnaar in het OP wordt verwezen. Tristan werkte in het WPV-team bij Microsoft, en bevestigt in feite.
@scottbb - alleen voor de 2e en volgende. We weten NIET wat er met de eerste gebeurt en dat is wat we hier proberen te achterhalen.
R.. GitHub STOP HELPING ICE
2016-11-07 22:20:32 UTC
view on stackexchange narkive permalink

JPEG-rotatie zonder verlies is alleen mogelijk zonder de introductie van grensartefacten als de afbeeldingsafmetingen veelvouden zijn van de blokgrootte (meestal [/ altijd?] 8). Zie de jpegtran-manpagina (sorry, ik heb er geen goede canonieke link voor; voel je vrij om te bewerken als je er een vindt) voor details over wat erbij komt kijken:

De transpositie-transformatie kent geen beperkingen wat betreft afbeelding
afmetingen. De andere transformaties werken nogal vreemd als de afbeeldingsafmetingen geen veelvoud zijn van de iMCU-grootte (gewoonlijk 8 of 16 pixels), omdat ze alleen volledige blokken DCT-coëfficiëntgegevens op de gewenste manier kunnen transformeren.

Het standaardgedrag van jpegtran bij het transformeren van een afbeelding met een vreemde grootte
is ontworpen om de exacte omkeerbaarheid en wiskundige consistentie van de transformatieset te behouden. Zoals gezegd, kan transponeren
het hele beeldgebied omdraaien. Bij horizontaal spiegelen blijft elke gedeeltelijke iMCU-kolom aan de rechterkant onaangeroerd, maar kunnen alle rijen van de afbeelding worden omgedraaid. Evenzo laat verticale spiegeling elke gedeeltelijke iMCU-rij aan de onderkant onaangeroerd, maar kan alle kolommen worden omgedraaid. De andere transformaties kunnen worden opgebouwd als reeksen van transponeer- en flipbewerkingen; voor consistentie zijn hun acties op randpixels gedefinieerd als hetzelfde als het eindresultaat van de corresponderende transpose-and-flip-reeks.

Voor praktisch gebruik kun je er de voorkeur aan geven om elke niet-transformeerbare
edge weg te gooien pixels in plaats van een vreemd uitziende strook langs de
rechter- en / of onderkant van een getransformeerde afbeelding. Om dit te doen, voegt u de -trim-schakelaar toe:

Ik vermoed dat de Windows Photo Viewer dit probleem vermijdt door decompressie en extreem hoogwaardige hercompressie uit te voeren om verliesloos gedrag te simuleren wanneer de afbeeldingsdimensies geen veelvouden van 8 zijn, in plaats van daadwerkelijk verliesloos roteren uit te voeren. Een goed hulpprogramma zou gewoon echt verliesvrij maken, artefacten en alles, of een paar pixels laten vallen, in plaats van de kwaliteit van de hele afbeelding te verpesten (en de bestandsgrootte te vergroten).

niet relevant voor een afbeelding van 256x256.
Ik heb het verkeerd gelezen en dacht dat het probleem bij de 257x257-versie lag.
Timothy
2016-11-09 05:14:29 UTC
view on stackexchange narkive permalink

Ik heb geen definitief antwoord, maar enkele mogelijke theorieën over waarom dat is gebeurd. Sommige bestandstypen werken op zo'n manier dat twee verschillende codes voor een afbeelding van dat bestandstype niet noodzakelijkerwijs verschillende afbeeldingen produceren. Het PNG-bestandstype werkt bijvoorbeeld op die manier omdat het een transparante achtergrond mogelijk maakt, maar een afbeelding met een transparante achtergrond en een afbeelding die hetzelfde is, behalve dat dezelfde achtergrond wit is, ziet er precies hetzelfde uit. Een afbeeldingsbestand is gecomprimeerd als het minder dan 3 bytes geheugen per pixel in beslag neemt. Ik denk dat behalve degene met een transparante achtergrond, geen twee PNG-bestanden exact dezelfde afbeelding genereren. Elke keer dat u een afbeelding opslaat als PNG, wordt deze omgezet in een code die de originele afbeelding genereert en behalve voor zeer ongebruikelijke afbeeldingen zoals een waarbij elke pixel een willekeurige kleur is van alle 2 ^ 24 kleuren, neemt de code minder geheugen in beslag dan 3 bytes per pixel, dus opslaan als PNG is compressie zonder verlies. Aan de andere kant kunnen alleen bepaalde afbeeldingen worden gegenereerd door de code van een JPEG-afbeeldingsbestand om geheugen te besparen. Er is waarschijnlijk meer dan één JPEG-bestandstype en ik weet niet of een ervan de eigenschap heeft dat twee verschillende afbeeldingen van dat bestandstype exact dezelfde afbeelding kunnen genereren. Ik neem aan dat je een aantal keren zojuist een afbeelding hebt geroteerd en deze vervolgens als JPEG hebt opgeslagen en ik zal een uitleg geven van wat er is gebeurd in de veronderstelling dat je dat deed en waarvan ik niet weet of het waar is. Een rotatie die u hebt gemaakt, is verliesloos als er een manier is om exact dezelfde afbeeldingsbestandscode terug te krijgen als voordat u deze roteerde en opsloeg. Je hebt misschien niet gelijk dat je echt een verliesloze rotatie hebt gedaan. Als het echt verliesvrij was, is een mogelijke reden dat twee verschillende afbeeldingscodes echt exact dezelfde afbeelding genereren en het was de code van de afbeelding die je had en niet de afbeelding die je had die de afbeelding bepaalde die je kreeg nadat je hem had geroteerd en vervolgens hebt opgeslagen het.

Cc Dd
2016-11-07 16:51:57 UTC
view on stackexchange narkive permalink

De redenen hiervoor zijn een paar

de manier waarop afbeeldingen worden gecodeerd en gecomprimeerd, verandert de grootte simpelweg vanwege het compressie-algoritme. u kunt dit testen door het op te slaan als een bitmap en vervolgens te roteren. In dat formaat of een ander onbewerkt formaat moet de grootte hetzelfde blijven. Als dit niet het geval is, voegt het programma dat de afbeelding opslaat nieuwe gegevens toe, mogelijk wat metadata of zoiets.

Maar waarom roteer je een jpeg 20 keer?

Als je de link in de oorspronkelijke vraag leest, _in ieder geval voor Windows Picture Viewer_, als de afmetingen van een JPEG een veelvoud zijn van 8, dan zijn rotaties van JPEGS _in WPV_ verliesloze transformaties. Een eenvoudige manier om dat te testen, is door 4 keer te roteren (wat resulteert in dezelfde oriëntatie als het origineel) en een eenvoudige pixel-voor-pixel afbeelding aftrekken.
@scottbb Dit is niet noodzakelijk alleen een probleem met Windows Picture Viewer. Alles dat een lossy-indeling roteert, moet de compressie opnieuw berekenen. het roteren van een afbeelding in veelvouden van 8 betekent dat alles in 8-bits woorden past en mogelijk niet wordt gecomprimeerd op een manier die artefacten toevoegt. Dit is gebaseerd op hoe het algoritme werkt en is geïmplementeerd in het gebruikte programma.
CoffeDeveloper
2016-11-07 19:54:09 UTC
view on stackexchange narkive permalink

Vanwege hoe compressie van afbeeldingen werkt . Elk formaat zoals PNG of JPG behoudt over het algemeen de bestandsgrootte niet na rotatie.

Voor de compressor is de geroteerde afbeelding gewoon een andere afbeelding, vanwege de manier waarop compressie-heuristiek werkt er is geen garantie dat het zal comprimeren een geroteerde afbeelding hetzelfde .

Natuurlijk, als de compressie verliesloos is, als je de afbeelding 4 keer roteert voor de 4e keer, is de afbeelding weer hetzelfde (geroteerd totdat het wordt gekanteld als origineel) : in dat geval zou het weer dezelfde gecomprimeerde grootte moeten krijgen, zo niet dan is dat vanwege een van de volgende redenen :

  • Toegevoegde metadata : het programma heeft om de een of andere reden wat tekst toegevoegd
  • Compressor gewijzigd: het programma kan ervoor kiezen om de afbeelding gewoon opnieuw op te slaan als het origineel als er geen wijzigingen zijn, maar als je een wijziging aanbrengt ( zelfs 4 rotaties van 90 graden), kan besluiten om de afbeelding opnieuw te comprimeren met zijn eigen compressor (het programma weet niet langer dat het nog steeds dezelfde afbeelding is).
  • In het algemeen levert dezelfde compressor (libPNG of libJPG) zeer verschillende resultaten op over verschillende implementaties, verschillende versies van dezelfde bibliotheek en met verschillende compressieparameters (ook het besturingssysteem en de compiler maken hier soms een verschil).

Beeldcompressie werkt door afbeeldingen te comprimeren in stukken van 4x4 of andere formaten. Over het algemeen ziet een compressor een geroteerd beeld als een ander beeld, maar aangezien een gecomprimeerd pixelblok slechts een lineaire decompositie is, is het mogelijk om, als de brokken op het beeld hetzelfde zijn, de lineaire decompositiematrices effectief hetzelfde te transponeren / spiegelen. kwaliteit:

Merk op dat dit moet worden geïmplementeerd per functie , en dat verklaart ook de initiële toename in grootte => bij de eerste rotatie probeert het gewoon de afbeelding te comprimeren in brokken die roteerbaar zijn:

  • Als dit niet lukt: de beeldkwaliteit verslechtert
  • Als het lukt, vergroot het de grootte slechts één keer, dan behoudt elke rotatie dezelfde kwaliteit.

  • Die bewerking is alleen succesvol als de afbeelding is gemaakt door gelijke delen . (grootte van de afbeelding is een veelvoud van de grootte van de brok).

Het antwoord van scottbb is verkeerd en je kunt een eenvoudige test doen:

  • Open de originele afbeelding: maak een screenshot
  • Draai de afbeelding 4 keer met WPV: maak een screenshot
  • Vergelijk de 2 screenshots

U zult het beeld zien veranderen (het wordt opnieuw gecomprimeerd bij de eerste rotatie). Die verandering is echter beperkt in de tijd, je kunt hem nu weer draaien zonder kwaliteitsverlies (als de afbeelding een grootte heeft die een veelvoud is van 8)

Om OP direct te beantwoorden:

Ik weet dat het verliesloos roteert

Het roteert niet zonder verlies, het verliest minstens één keer aan kwaliteit (bij de eerste rotatie: omdat het het eerst zou moeten comprimeren op een manier die kan worden gedraaid), dan behoudt het zijn kwaliteit.

De vraag gaat over verliesloze rotatie, dus hercompressie wordt vermeden.
Ik programmeer een grafische editor, zodat ik weet wat ik zeg, wanneer het bestand wordt opgeslagen => het is gecomprimeerd. Wat in ieder geval aan het bestand wordt toegevoegd, is "rotatie" -informatie.
Ik weet wat ik zeg en heb zelfs een beeldcompressor geïmplementeerd. Het is mogelijk als je dat alleen voor rotatie implementeert (wat betekent dat je weet dat rotatie de enige verandering in de afbeelding is), in het algemeen is dit niet mogelijk. Het lijkt erop dat de ontwikkelaars van Windows Photo Editor die truc hebben gedaan
OP vroeg niet naar het algemene geval, maar precies naar dat ene stuk specifieke software en dat ene specifieke geval dat het doet. Uw antwoord is niet verkeerd, het beantwoordt alleen een andere vraag dan wat OP vroeg.
Nee, het antwoordt. Lees het opnieuw. Ik heb dat een tijdje geleden bewerkt.
De eerste 3 zinnen gaan nog steeds over een andere vraag: "hoe compressie van afbeeldingen werkt" - er is geen compressie bij verliesloze rotatie. "Naar de compressor de geroteerde afbeelding" - nogmaals, de compressor wordt niet aangeroepen. "als de compressie zonder verlies is" - de compressie is met verlies. De rotatie is verliesloos. Dit is hoe ver ik bereid ben dit argument te voeren. Ik begrijp je punt, ik ben het ermee eens, maar het past hier helemaal niet. Trouwens, ik ben ook een programmeur en ik heb mijn aandeel in het lezen en schrijven van onbewerkte bestanden gedaan.
Dat lijkt u te persoonlijk op te vatten. HET IS GEEN LOSSLESS ROTATION: lees gewoon het kleine experiment en doe dat zelf. Het laat in feite zien dat uw laatste opmerking onjuist is. U.u Je bent misschien zelfs een programmeur, maar ik geloof niet dat je ooit een beeldcompressor hebt gecodeerd (zelfs een eenvoudigere)
Het spijt me dan, welk experiment kan ik doen om het te laten zien? Omdat er een experiment is gedaan in de gekoppelde vraag. Interpreteer ik de resultaten verkeerd?
Ik heb een afbeelding gemaakt in Paint, deze 4 keer geroteerd en hij is identiek, maar de grootte is desondanks gestegen van 1,6 naar 8,1 KB. Binaire diff laat zien dat afbeeldingsgegevens onaangetast waren, het is gewoon een enorm stuk metadata in `
PAint-afbeelding is geen goede kandidaat u.u Ik heb net het experiment gedaan met een echte foto .. Heb je een afbeelding anders gebruikt? Sorry maar welke Windows-versie heb je?
Ik nam een ​​screenshot, plakte het in verf en sneed het bij tot 128x128. Het lijkt erop dat hetzelfde stuk kerngegevens wordt herhaald, maar de geroteerde versie heeft een enorm stuk bijna lege `
Als de afmetingen van een JPEG gelijkmatig deelbaar zijn door 8 (of 16 met subsampling), kan deze worden geroteerd in stappen van 90 graden * zonder verlies *. De sleutel is om het * niet * helemaal naar RGB te decoderen, maar om rechtstreeks met de DCT-coëfficiënten te werken. Het is een gespecialiseerde functie die niet vaak wordt gebruikt in een algemene afbeeldingseditor. Zie bijvoorbeeld https://en.wikipedia.org/wiki/Libjpeg#jpegtran. Als u uw experiment met * Windows Photo Viewer * hebt uitgevoerd zoals gespecificeerd in de vraag, zou u zien dat het inderdaad verliesvrij is.


Deze Q&A is automatisch vertaald vanuit de Engelse taal.De originele inhoud is beschikbaar op stackexchange, waarvoor we bedanken voor de cc by-sa 3.0-licentie waaronder het wordt gedistribueerd.
Loading...