Jeśli obraz jest obracany bezstratnie, dlaczego zmienia się rozmiar pliku?

37

Szukałem metod bezstratnego obracania obrazu i natrafiłem na to pytanie, które dość ładnie to wyjaśnia:

Czy obroty „Windows Photo Viewer” są bezstratne?

Utworzyłem więc 256 × 256 JPEG z losowymi pikselami (filtr chmurowy Photoshopa), a następnie obróciłem go za pomocą Windows Picture Viewer. Po obróceniu rozmiar pliku faktycznie się zwiększył, ale tylko przy pierwszym obrocie. Po każdym kolejnym obrocie rozmiar pliku pozostawał statyczny. Wiem, że obraca się bezstratnie, ponieważ obróciłem go wiele razy bez zauważalnej utraty jakości, podczas gdy obraz 257 × 257 obracany 20 razy stał się bardzo stratny.

kretyna oscylacyjna
źródło
8
O ile zwiększył się rozmiar pliku w twoich testach?
James Snell,
3
@JamesSnell Wiedziałem, że powinienem to uwzględnić. Ten, który właśnie zrobiłem przy użyciu filtru różnicowego GIMP, miał pierwotnie 14 583 bajtów, ale po roationie zmienił się na 23 638 bajtów. To różnica ponad 9000 bajtów, co wydaje się dużą ilością dodatkowych danych, jeśli mówimy o samych metadanych.
oscilatingcretin
4
To wygląda na wiele dodatkowych metadanych. Nie byłbym zbyt szybki, aby założyć, że wszystkie te dodatkowe dane są metadanymi. Wydaje mi się, że różnica wielkości wynikająca z metadanych powinna być prawie stała (w ciągu kilku bajtów, aby uwzględnić ciąg znaków niektórych liczb).
scottbb,
4
Podając dodatkowe informacje związane z pytaniem, edytuj je w pytaniu, a nie w komentarzach. Komentarze są efemeryczne i od czasu do czasu mogą zostać usunięte.
scottbb,
2
Pomocne byłoby przesłanie oryginalnej wersji obrazu testowego.
CodesInChaos

Odpowiedzi:

36

Jest to najprawdopodobniej spowodowane kodowaniem entropijnym , które jest ostatnim bezstratnym etapem kompresji JPEG, po kwantowaniu danych obrazu w celu zmniejszenia jego rozmiaru.

Gdy obraz JPEG jest bezstratnie obracany, ta ostatnia bezstratna warstwa kodowania musi zostać cofnięta, rozpakowane współczynniki DCT są przetasowane, a następnie tasowane współczynniki muszą zostać ponownie zakodowane entropijnie. Ponieważ wydajność warstwy kodującej entropię zależy od rzędu współczynników DCT w każdym bloku, który zmieni się obracając obraz, nie powinno dziwić, że obrócony plik obrazu może być kilka procent mniejszy lub większy niż oryginał.

Istnieje również kilka różnych sposobów, w jakie można wykonać krok kodowania entropijnego, więc jest całkiem możliwe, że rozmiar pliku dokładnie tego samego obrazu JPEG może się różnić w zależności od oprogramowania, które wykonuje kodowanie. Niektóre potencjalne różnice między koderami obejmują:

  • wybór kodowania arytmetycznego (rzadkie, ale potencjalnie bardziej wydajne, kiedyś opatentowane) w porównaniu z kodowaniem Huffmana (prostsze, standardowe);
  • wybór sekwencyjnego (każdy blok 8 x 8 pikseli jest kodowany pojedynczo) vs. progresywnego (składowe niskiej częstotliwości wszystkich bloków są kodowane przed składnikami wyższej częstotliwości, zwykle nieco bardziej zwartymi);
  • wybór użycia standardowych tabel symboli Huffmana (szybsze, prostsze, mogą być bardziej wydajne w przypadku bardzo małych obrazów) w porównaniu do tabel niestandardowych zoptymalizowanych dla każdego obrazu (zwykle bardziej wydajnych w przypadku dużych obrazów, wolniejszych i bardziej skomplikowanych do kodowania);
  • jeśli stosowane są niestandardowe tabele Huffmana, różne kodery mogą potencjalnie generować różne tabele dla tych samych danych obrazu;
  • różne szczegóły niskiego poziomu samego procesu kodowania, takie jak to, czy i kiedy uwzględnić znaczniki restartu w strumieniu danych, mogą również różnić się w zależności od kodera.

Ponadto „pliki JPEG”, z którymi zwykle pracują ludzie, zawierają dane obrazu skompresowane w formacie JPEG, opakowane w JFIF lub kontener Exif , który łączy dane obrazu z jednym lub większą liczbą bloków metadanych i wprowadza własny zestaw komplikacji. Nawet jeśli oprogramowanie, które obraca obraz, nie wprowadza żadnych istotnych zmian w metadanych JFIF / Exif, po prostu zmiana kolejności danych może potencjalnie wpłynąć na rozmiar pliku o kilka bajtów.

W szczególności metadane JFIF / Exif mogą zawierać jedną lub więcej miniaturek pełnowymiarowego obrazu, a oprogramowanie, które obraca obrazy, powinno naprawdę zregenerować (lub też bezstratnie obrócić!) Miniatury, aby dopasować je do nowej orientacji pełnego- rozmiar obrazu. Już to samo z łatwością może uwzględnić zaobserwowaną różnicę wielkości.

Ilmari Karonen
źródło
4
W przypadku różnicy 9 KB (60%) domyślam się, że będą to miniatury.
BlueRaja - Danny Pflughoeft
JPEG może być zbyt proste, aby było to warte koderów, ale kodery wideo, takie jak x264, mogą faktycznie wziąć pod uwagę zdolność kodera wejściowego do kodowania tego, co mają zamiar wydrukować w następnej kolejności, przy podejmowaniu decyzji dotyczących kompromisu między współczynnikiem a zniekształceniem. (tj. decydując, ile bitów może kosztować każda alternatywa, i porównując to z błędem stratnym). Nazywa się to kwantyzacją kratową. Patrz uwagi na temat implementacji kwantyzacji kratki w H.264 od autora x264 (Loren Merritt); zaczyna od dość podstawowego wyjaśnienia celu.
Peter Cordes,
W każdym razie, koder JPEG mógł tak dobrać współczynniki DCT, że dobrze skompresowały się z koderem entropijnym, więc nawet optymalny kompresor nie mógł zrobić wersji obróconej tak małej. (Ponieważ umieszczenie ich w innej kolejności prawdopodobnie spowodowałoby, że kompresują się gorzej.) Byłoby to prawie na pewno niewielki efekt dla JPEG, ponieważ każdy blok 8x8 jest kodowany osobno (resetowanie stanu kodera entropijnego, AFAIK). (Ramki I w h.264 używają predykcji intra, przewidując z innych bloków w tej samej ramce, co czyni je mniejszymi niż JPEG o tej samej jakości wizualnej.)
Peter Cordes
24

Poszedłem dalej i powtórzyłem eksperyment, aby sprawdzić, czy mogę się dowiedzieć, co się dzieje.

Procedura

Wygenerowałem losowy obraz RGB 256 na 256 pikseli przy użyciu filtra „Solid Noise” w GIMP (Filtry> Renderowanie> Chmury> Solid Noise ...) przy użyciu ustawień domyślnych (pokazanych poniżej):

wprowadź opis zdjęcia tutaj

A wynik:

wprowadź opis zdjęcia tutaj

Następnie zapisałem obraz jako JPEG przy użyciu ustawień domyślnych:

wprowadź opis zdjęcia tutaj

Następnie przeniosłem obraz do systemu Windows i otworzyłem go za pomocą Przeglądarki fotografii systemu Windows, klikając obraz prawym przyciskiem myszy w Eksploratorze plików i wybierając z menu opcję Podgląd . Następnie obróciłem obraz za pomocą przycisków na dole i zapisałem obraz, przechodząc do następnego obrazu za pomocą klawiszy strzałek.

Dla każdego z poniższych testów zacząłem od kopii oryginalnego obrazu i obróciłem (kliknąłem przycisk obrotu) odpowiednią liczbę razy przed zapisaniem. Oto rozmiary resltingu ( 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

Natychmiastowe obserwacje

  • Windows Photo Viewer (WPV) znacznie zwiększa rozmiar; w tym teście kwota wzrostu jest około cztery razy!
  • Wszystkie nowe obrazy powiększają się do mniej więcej tego samego rozmiaru, ale nie są identyczne.
  • WPV nie koduje ani nawet nie zapisuje obrazu, gdy zostanie on obrócony o wielokrotność 360 stopni. (Znacznik czasu 11:27 oznacza datę pierwszego skopiowania plików).

Używanie cmp -lplików, które powinny mieć identyczną treść, pozwala nam zobaczyć, gdzie różnią się pliki.

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

Pliki te różnią się tylko czterema bajtami (w rzeczywistości znacznikiem czasu), co oznacza, że ​​WPV robi to samo za każdym razem; teraz musimy tylko dowiedzieć się, co to jest.

Szczegółowe obserwacje

W tym celu użyłem JPEGsnoop, aby zobaczyć, co dokładnie jest na obrazach.

Ponieważ wyniki są dość długie, powiązałem je z nimi jako sedno . Oto podsumowanie różnic:

  • GIMP używa tylko segmentu APP0(JFIF) i COM(komentarza) dla metadanych. WPV pozostawia APP0segment nietknięty, ale z ciekawością dodaje bajt zerowy do komentarza (tak, że jest zakończony zerem ).

  • WPV dodaje dwa APP1segmenty, które są metadanymi Exif i XMP. Segmenty te mają odpowiednio 4286 i 12726 bajtów. Razem stanowią prawie cały wzrost wielkości plików.

  • GIMP tworzy progresywny JPEG, podczas gdy WPV tworzy wyjściowy (nie progresywny) JPEG. Z tego powodu obraz GIMP ma wiele segmentów skanowania, podczas gdy obraz WPV ma tylko jeden. Z mojego doświadczenia wynika, że ​​obraz progresywny jest czasem nieco mniejszy.

  • GIMP zastosował podpróbkowanie 1 × 1, a WPV zastosował podpróbkowanie 2 × 2. To prowadzi mnie do przekonania, że ​​WPV nie używa „prawdziwej” bezstratnej rotacji, chyba że w jakiś sposób jest w stanie wykryć, że jest to obraz czarno-biały.

Aby rozwiązać te problemy, przeprowadziłem drugi test.

Procedura

Wykonałem podobne kroki do pierwszego testu. Utworzyłem losowy obraz RGB 256 × 256 przy użyciu filtra szumów RGB (Filtry> Nos> Nos RGB ...) z następującymi ustawieniami:

wprowadź opis zdjęcia tutaj

Oto wynik:

wprowadź opis zdjęcia tutaj

Wyeksportowałem plik jako JPEG przy użyciu następujących ustawień:

wprowadź opis zdjęcia tutaj

Progresywne zostało wyłączone, ale podpróbkowanie jest nadal ustawione na 4: 4: 4 (co jest inną nazwą dla podpróbkowania 1 × 1). Jakość zostaje zwiększona do 98.

Skopiowałem obraz i obróciłem kopię w prawo; następnie skopiowałem obróconą wersję i obróciłem tę kopię przeciwnie do ruchu wskazówek zegara, abyśmy mogli bezpośrednio porównać jakość oryginału i przetworzonej kopii WPV.

Wyniki

-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

Chociaż wzrost ten czas jest mniejszy w kategoriach względnych (około 40%), wzrost absolutny jest jeszcze większy - około 62 kB. Sugeruje to, że WMV używa mniej wydajnego kodowania.

Użyję ImageMagick porównać dwa obrazy:

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

zerowe pikseli różne między pierwotnym i obróconej kopii. Tak więc, nawet jeśli WPV nie używa „prawdziwej” bezstratnej rotacji, robi wystarczająco dobrą robotę. Podejrzewam, że wiem, co się dzieje, i aby wyjaśnić, przejdę trochę do matematyki związanej z kompresją JPEG.

Algorytm kompresji JPEG dzieli obraz na bloki 8 x 8 pikseli. Każdy z tych bloków jest następnie poddawany dyskretnej transformacji kosinusowej (DCT) . Otrzymane współczynniki DCT opisują blok jako sumę fal o różnych częstotliwościach. Algorytm następnie „wyrzuca” w falach o wysokiej częstotliwości pewne informacje, które odpowiadają szumowi i bardzo małym szczegółom. Proces dekodowania odwraca DCT, dodając zgromadzone fale razem, aby odzyskać blok.

Możliwe jest obracanie „fal” DCT bez faktycznego cofania i ponawiania transformacji (w zasadzie zamieniasz wszystkie fale poziome na fale pionowe i odwrotnie). Wydaje mi się, że w WPV obraz jest dekodowany, obracany, a następnie ponownie kodowany. Podczas procesu ponownego kodowania, ponieważ rozmiar naszego obrazu jest wielokrotnością 8 w obu wymiarach, każdy z nowych bloków odpowiada jednemu z oryginalnych bloków. Co ważne, ponieważ każdy blok nie ma składników o wysokiej częstotliwości, algorytm nie wyrzuca żadnych informacji i znajduje dokładnie odpowiednie składniki DCT, które miałby „prawdziwy” bezstratny obrót.

Na koniec jeszcze raz przyjrzę się składnikom plików JPEG. Wyniki są ponownie łączone jako istoty . Porównując dwa:

  • Obraz WPV zawiera dodatkowe 4286 + 2 bajty metadanych Exif, 1 dodatkowy bajt w komentarzu i 12 726 + 2 bajty metadanych XMP. Jest to łącznie 17.017 bajtów dodatkowych metadanych. Do czego służą wszystkie te dane? Zerknąłem do pliku z moim zaufanym edytorem szesnastkowym i kopią odpowiednich standardów:

    • Metadane Exif mają strukturę podobną do obrazu TIFF, który zawiera wiele tagów (jest o wiele bardziej złożona, ale przeskoczę nad tym). Większość bajtów w segmencie Exif znajduje się w dwóch identycznych znacznikach o numerze EA1C(59 932 dziesiętnym). Tego numeru znacznika nie udokumentowano nigdzie, gdzie mogłem znaleźć. Oba tagi zawierają 2060 bajtów typu „niezdefiniowany”, które są bajtami zerowymi, z wyjątkiem pierwszych sześciu ( 1C EA 00 00 00 08). Nie mam pojęcia, co to za tagi, dlaczego są dwa i dlaczego muszą mieć 2 kB każdy.

    • Metadane XMP to tak naprawdę cały osadzony dokument XML z przestrzenią nazw i długimi identyfikatorami UUID, który zawiera tylko ciąg wersji WPV (który był już w metadanych Exif). Jednak to tylko około 400 bajtów. Pozostała część segmentu to 122 powtórzenia 100 spacji, po których następuje nowa linia . To ponad 12 000 bajtów całkowicie zmarnowanej przestrzeni.

  • Podobnie jak w poprzednim teście, zarówno GIMP, jak i WPV używają tych samych tabel kwantyzacji DCT. Oznacza to, że powinni obliczać dokładnie te same współczynniki DCT, dlatego obrazy są dokładnie takie same. Nie jestem pewien, czy WPV po prostu używa tych samych tabel kwantyzacji, czy kopiuje je z danych wejściowych.

  • W przeciwieństwie do poprzedniego testu, tym razem WPV korzysta z podpróbkowania 1 × 1, więc może faktycznie wykryć, że jest to kolorowy obraz (lub przynajmniej, że wyższe próbki są konieczne do bezstratnego ponownego kodowania obrazu).

  • GIMP i WPV używają różnych tabel Huffmana (część etapu kodowania entropijnego). Tabele WPV są większe o łącznie 279 bajtów, aw jednym przypadku zawierają 7 razy więcej kodów.

    Patrząc na statystyki JPEGsnoop, widzimy, że niektóre z tych kodów są rzadko używane. Na przykład w ID: 1, Class: ACtabeli spośród 119 zdefiniowanych 16-bitowych kodów faktycznie używanych jest tylko 23. Ogólnie rzecz biorąc, rzeczywisty segment skanowania jest o 28,5% większy w wersji WPV.

Podsumowanie

  • WPV może nie wykonywać „prawdziwych” obrotów bezstratnych, ale wydają się być praktycznie bezstratne.

  • Dodatkowy rozmiar wynika częściowo ze stałej ilości dodanych metadanych, a częściowo z mniej wydajnego kodowania entropii.

Informacje o wersji:

  • System operacyjny (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
    
  • System operacyjny (Windows):

    wprowadź opis zdjęcia tutaj

  • GIMP (Linux): 2.8.14 (z pakietu gimp, wersja 2.8.14-1+deb8u1)

    wprowadź opis zdjęcia tutaj

  • Przeglądarka zdjęć w oknie (zgodnie z metadanymi obrazu):

    Microsoft Windows Photo Viewer 10.0.10586.0
    
2012 rcampion
źródło
20

EDYCJA : Ta odpowiedź została opublikowana, zanim dowiedziałem się, że rozmiar plików zwiększył się o około 9 KiB (9055 bajtów dla obrazu 256 × 256, 9612 KiB dla obrazu 512 × 512).

Najprawdopodobniej po pierwszym obróceniu obrazu Przeglądarka obrazów systemu Windows wykonała jedną (lub obie) następujące czynności:

  1. Dodano znacznik EXIF, który nie był w oryginalnym obrazie JPEG (być może znacznik Orientacji);
  2. Zmodyfikowano / dodano informacje do znacznika, który już istniał (być może znaczniki oprogramowania przetwarzającego lub oprogramowania obrazowego).

Zwiększyło to rozmiar pliku z powodu dodatkowego znacznika EXIF ​​(i / lub dodatkowych danych do istniejących znaczników).

Kolejne rotacje nie zwiększyły rozmiaru pliku, ponieważ wszystkie znaczniki i / lub dane znaczników, które WPV dodałby / zmodyfikowałoby już tam były. Zmieniła się tylko wartość znacznika orientacji (i być może również wartości znacznika daty / godziny).


EDYCJA : Jest prawie pewne, że to wyjaśnienie nie może uwzględniać około 9 KiB dodatkowych danych w pliku. Ponadto, bez jakichkolwiek innych przyczyn wzrostu rozmiaru, wyjaśnienie to oczekiwałoby, że wzrost wielkości byłby mniej więcej stały (modulo pewne różnice długości między reprezentacjami łańcuchowymi danych liczbowych, prawdopodobnie kilka bajtów). To oczywiście nie dzieje się tutaj, a przynajmniej nie pełne wyjaśnienie.

scottbb
źródło
1
A tag EXIF ​​zajmie 9kB? Cóż, przynajmniej jest to łatwe do przetestowania - poproś OP o usunięcie EXIF ​​lub innych znaczników z obróconego obrazu i zobacz, jak zmienia się rozmiar pliku.
Carl Witthoft,
2
@CllWitthoft 9kB to nowa informacja. Edytowanie, żeby o tym wspomnieć.
scottbb,
3

Bez inżynierii odwrotnej jpeg en / dekoder nie jest pewne. W rzeczywistości istnieje wiele standardów JPEG i wbrew powszechnemu przekonaniu, nie wszystkie z nich można modyfikować bez ponownego kodowania.

Możliwe, że pierwszy zapis jest stratnym przepisywaniem do ulubionego smaku jpeg, a kolejne obroty są prostą poprawką metadanych lub operacją bezpośrednio na tablicy DCT (co jest możliwe w przypadku niektórych schematów kodowania).

Zwiększenie rozmiaru plików może również obejmować dodatkowe metadane, chociaż 9k wydaje się dużo, jest to możliwe. Wzrost ten można również uwzględnić poprzez dodanie miniatury, która mogła nie występować w danych wyjściowych GIMP. Możemy być w stanie uzyskać więcej informacji z plików bezpośrednio (przed WPV i po).

W każdym razie próba bezproblemowej pracy z JPEG jest naprawdę głupcem, ponieważ jest przydatna tylko w przypadku niektórych rozmiarów obrazów, nie wszystkie dekodery i kodery są identyczne i wymaga od tych redaktorów bezpośredniej pracy z treściami JPEG, na których nie można polegać. przypadek ... To, że teraz tak się dzieje, nie oznacza, że ​​będzie tak w przyszłości.

Lepiej jest pracować w formacie bezstratnym i całkowicie unikać bólu.

James Snell
źródło
2
Wcale nie jestem przekonany, że obracanie danych JPEG powinno przede wszystkim powodować ponowne kodowanie.
Carl Witthoft,
Zależy, czy jesteś programistą czy nie ... Domyślam się, że nie jesteś. Trzeba było specjalnie szukać tej optymalizacji, aby wprowadzić tę minimalną zmianę, w przeciwnym razie operacja składowania rozpocznie się od nieskompresowanej mapy bitowej.
James Snell,
3
Z połączonego pytania wynika, że ​​przeglądarka zdjęć Windows bezstratnie obraca pliki JPEG.
vclaw
2
@James Nie jestem programistą niskiego poziomu, ponieważ gram w telewizji :-). OP podał link do dokładnego opisu, kiedy nastąpi ponowne kodowanie, a kiedy nie. Z tej dyskusji wywnioskowałem, że obracał się tylko o $ \ frac {\ pi} {2} $. Zgadzam się, że dowolny obrót kąta powoduje ponowne kodowanie i dlatego spowoduje utratę informacji, chyba że obraz X-by-Y zostanie osadzony w obszarze co najmniej tak dużym jak przeciwprostokątna.
Carl Witthoft,
1
Jesteśmy prawie pewni, że wiemy, że WPV obraca się odwracalnie dla obrazów o wielokrotności wymiarów 8/16. Zobacz komentarz @ Tristana do odpowiedzi Matta Gruma na pytanie powiązane z PO. Tristan pracował w zespole WPV w firmie Microsoft i zasadniczo potwierdza.
scottbb,
1

Bezstratny obrót JPEG jest możliwy tylko bez wprowadzenia artefaktów brzegowych, jeśli wymiary obrazu są wielokrotnościami wielkości bloku (zwykle [/ zawsze?] 8). Zobacz stronę podręcznika użytkownika jpegtran (przepraszam, że nie mam dobrego linku kanonicznego; możesz go edytować, jeśli znajdziesz), aby uzyskać szczegółowe informacje na temat tego, co się wiąże:

Transformacja transpozycji nie ma ograniczeń dotyczących
wymiarów obrazu . Inne transformacje działają raczej dziwnie, jeśli wymiary obrazu nie są wielokrotnością wielkości iMCU (zwykle 8 lub 16 pikseli), ponieważ mogą one tylko w pożądany sposób przekształcać pełne bloki danych o współczynniku DCT.

Domyślne zachowanie jpegtran podczas transformowania obrazu o nieparzystych rozmiarach
ma na celu zachowanie dokładnej odwracalności i matematycznej
spójności zestawu transformacji. Jak wspomniano, transpozycja jest w
stanie obrócić cały obszar obrazu. Odbicie lustrzane w poziomie pozostawia nietkniętą część częściowej kolumny iMCU na prawej krawędzi, ale jest w stanie odwrócić wszystkie rzędy obrazu. Podobnie, pionowe odbicie lustrzane pozostawia nietknięty dowolny częściowy rząd iMCU na dolnej krawędzi, ale jest w stanie odwrócić wszystkie kolumny. Inne transformacje mogą być budowane jako sekwencje operacji transpozycji i przerzucania; dla spójności ich działania na pikselach krawędzi są zdefiniowane jako takie same, jak wynik końcowy odpowiedniej sekwencji transpozycji i odwrócenia.

Dla praktycznego zastosowania możesz raczej odrzucić dowolne nietransformowalne
piksele krawędziowe zamiast dziwnie wyglądającego paska wzdłuż
prawej i / lub dolnej krawędzi przekształconego obrazu. Aby to zrobić, dodaj przełącznik -trim:

Podejrzewam, że Windows Photo Viewer unika tego problemu, wykonując dekompresję i rekompresję o bardzo wysokiej jakości w celu symulacji bezstratnego zachowania, gdy wymiary obrazu nie są wielokrotnością 8, zamiast faktycznego wykonywania bezstratnego obrotu. Dobra użyteczność po prostu wykonałaby rzeczywiste bezstratne artefakty i wszystko lub upuściła kilka pikseli, zamiast zniszczyć jakość całego obrazu (i zwiększyć rozmiar pliku).

R ..
źródło
1
nie ma znaczenia dla obrazu 256 x 256.
ths
Źle odczytałem i pomyślałem, że problem dotyczy wersji 257x257.
R ..
0

Nie mam jednoznacznej odpowiedzi, ale kilka możliwych teorii, dlaczego tak się stało. Niektóre typy plików działają w taki sposób, że dwa różne kody dla obrazu tego typu pliku niekoniecznie generują różne obrazy. Na przykład typ pliku PNG działa w ten sposób, ponieważ pozwala na przezroczyste tło, ale obraz z przezroczystym tłem i taki sam, z tym wyjątkiem, że to samo tło jest białe, wygląda dokładnie tak samo. Mówi się, że plik obrazu jest skompresowany, jeśli zajmuje mniej niż 3 bajty pamięci na piksel. Uważam, że oprócz plików z przezroczystym tłem, żadne dwa pliki PNG nie generują dokładnie tego samego obrazu. Kiedy zapisujesz obraz jako PNG, konwertuje go na kod, który generuje oryginalny obraz, z wyjątkiem bardzo nietypowych obrazów, takich jak jeden, w którym każdy piksel jest losowym kolorem wszystkich 2 ^ 24 kolorów, kod zajmie mniej pamięci niż 3 bajty na piksel, więc oszczędza się, ponieważ PNG jest kompresją bezstratną. Z drugiej strony, aby zaoszczędzić pamięć, tylko niektóre obrazy mogą być generowane przez kod pliku obrazu JPEG. Prawdopodobnie istnieje więcej niż jeden typ pliku JPEG i nie wiem, czy któryś z nich ma właściwość, że dwa różne obrazy tego typu pliku mogą wygenerować dokładnie ten sam obraz. Zakładam, że kilka razy po prostu obróciłeś obraz, a następnie zapisałeś go jako JPEG i podam wyjaśnienie tego, co się wydarzyło przy założeniu, że to właśnie zrobiłeś, ale nie wiem, czy to prawda. Wykonany obrót jest bezstratny, jeśli istnieje sposób na odzyskanie dokładnie takiego samego kodu pliku obrazu, jaki był przed obróceniem go i zapisaniem. Być może nie masz racji, że wykonałeś rotację bezstratną. Jeśli to naprawdę było bezstratne,

Tymotka
źródło
-3

Przyczyny tego są kilka

sposób kodowania i kompresji obrazów zmieni rozmiar po prostu z powodu algorytmu kompresji. możesz to przetestować, zapisując go jako mapę bitową, a następnie obracając. W tym formacie lub dowolnym innym nieprzetworzonym formacie rozmiar powinien pozostać taki sam. Jeśli nie, program zapisujący obraz dodaje nowe dane, być może jakieś metadane lub coś takiego.

Ale dlaczego obracasz JPEG 20 razy?

DW Dd
źródło
2
Jeśli przeczytasz link w pierwotnym pytaniu, przynajmniej w przeglądarce Windows Picture Viewer , jeśli wymiary JPEG są wielokrotnością 8, wówczas obrót JPEGS w WPV jest bezstratną transformacją. Prostym sposobem na przetestowanie jest 4-krotne obrócenie (w tej samej orientacji co oryginał) i wykonanie prostego odejmowania obrazu piksel po pikselu.
scottbb,
@scottbb To niekoniecznie jest tylko problem z przeglądarką obrazów systemu Windows. Wszystko, co obraca format stratny, musi ponownie obliczyć kompresję. obrócenie obrazu o wielokrotność 8 oznacza, że ​​wszystko mieści się w 8-bitowych słowach i może nie zostać skompresowane w sposób, który dodaje artefakty. Jest to oparte na działaniu algorytmu i jest zaimplementowane w używanym programie.
Cc Dd
-3

Ze względu na sposób kompresji obrazów . Żaden format, taki jak PNG lub JPG, ogólnie nie zachowuje rozmiaru pliku po rotacji.

Dla kompresora obrócony obraz jest po prostu innym obrazem, ze względu na to, jak działa heurystyka kompresyjna, nie ma gwarancji, że skompresuje obrócony obraz w ten sam sposób .

Oczywiście, jeśli kompresja jest bezstratna, jeśli obrócisz obraz 4 razy 4 razy, obraz będzie znowu taki sam (obrócony, aż zostanie pochylony jak oryginał): w takim przypadku powinien ponownie uzyskać ten sam skompresowany rozmiar, jeśli nie wtedy wynika to z jednego z następujących powodów :

  • Dodano metadane : program z jakiegoś powodu dodał kawałek tekstu
  • Zmieniono kompresor: program może po prostu ponownie zapisać obraz jako oryginał, jeśli nie ma żadnych zmian, ale jeśli zastosujesz dowolną zmianę (nawet 4 obroty o 90 stopni), może zdecydować o ponownym skompresowaniu obrazu za pomocą własnego kompresor (program nie wie już, że to wciąż ten sam obraz).
  • Ogólnie rzecz biorąc, ten sam kompresor (libPNG lub libJPG) daje bardzo różne wyniki w różnych implementacjach, różnych wersjach tej samej biblioteki i przy różnych parametrach kompresji (czasami system operacyjny i kompilator ma tu znaczenie).

Kompresja obrazu polega na kompresji obrazów do fragmentów 4x4 lub innych rozmiarów. Zasadniczo kompresor widzi obrócony obraz jako inny obraz, jednak ponieważ fragment skompresowanego piksela jest po prostu rozkładem liniowym, jeśli fragmenty na obrazie są takie same, możliwe jest po prostu transponowanie / odbicie lustrzane matryc liniowego rozkładu skutecznie utrzymując to samo jakość:

Uwaga: należy to zaimplementować dla poszczególnych obiektów , a to także wyjaśnia początkowy wzrost wielkości => przy pierwszym obrocie, po prostu próbuje skompresować obraz w częściach, które są obrotowe:

  • Jeśli tego nie zrobi: jakość obrazu ulegnie pogorszeniu
  • Jeśli się powiedzie, zwiększy rozmiar tylko raz, a następnie każdy obrót utrzyma tę samą jakość.

  • Ta operacja kończy się powodzeniem tylko wtedy, gdy obraz jest wykonany z jednakowych porcji. (rozmiar obrazu jest wielokrotnością wielkości fragmentu).

Odpowiedź scottbb jest nieprawidłowa i możesz wykonać prosty test:

  • Otwórz oryginalny obraz: Zrzut ekranu
  • Obróć obraz 4 razy za pomocą WPV: Zrzut ekranu
  • Porównaj 2 zrzuty ekranu

Zobaczysz obraz zmieniony (jest ponownie kompresowany przy pierwszym obrocie). Jednak ta zmiana jest ograniczona czasowo, możesz teraz obrócić ją ponownie bez utraty jakości (jeśli obraz ma rozmiar będący wielokrotnością 8)

Aby bezpośrednio odpowiedzieć OP:

Wiem, że obraca się bezstratnie

Nie obraca się bezstratnie, traci jakość co najmniej raz (przy pierwszym obrocie: ponieważ najpierw powinien go skompresować w sposób, który można obracać), a następnie zachowuje swoją jakość.

Twórca gier
źródło
1
Pytanie dotyczy rotacji bezstratnej, więc unika się ponownej kompresji.
Agent_L,
5
OP zapytał nie o ogólny przypadek, ale dokładnie o ten konkretny program i ten konkretny przypadek, który to robi. Twoja odpowiedź nie jest zła, po prostu odpowiada na inne pytanie niż na OP.
Agent_L,
1
Pierwsze 3 zdania wciąż mają inne pytanie: „jak działa kompresja obrazów” - brak kompresji w bezstratnym obrocie. „Do kompresora obrócony obraz” - ponownie kompresor nie jest wywoływany. „jeśli kompresja jest bezstratna” - kompresja jest stratna. Rotacja jest bezstratna. Oto, jak daleko jestem skłonny podjąć ten argument. Rozumiem twój punkt widzenia, zgadzam się z tym, ale tutaj jest to zupełnie nie na miejscu. BTW, ja też jestem programistą i miałem swój udział w czytaniu i zapisywaniu plików raw.
Agent_L,
1
Utworzyłem obraz w programie Paint, obróciłem go 4 razy i jest on identyczny, ale jego rozmiar skoczył z 1,6 do 8,1 KB. Różnica binarna pokazuje, że dane obrazu pozostały nietknięte, to po prostu ogromny fragment metadanych w <?xpackettagach.
Agent_L,
1
Jeśli wymiary JPEG są równomiernie podzielne przez 8 (lub 16 z podpróbkowaniem), można je bezstratnie obracać o 90 stopni . Kluczem jest nie dekodowanie go aż do RGB, ale bezpośrednia praca ze współczynnikami DCT. Jest to specjalistyczna funkcja, która często nie jest zawarta w ogólnym edytorze obrazów. Zobacz na przykład en.wikipedia.org/wiki/Libjpeg#jpegtran . Jeśli przeprowadziłeś eksperyment z programem Windows Photo Viewer, jak określono w pytaniu, zobaczysz, że jest on rzeczywiście bezstratny.
Mark Ransom,