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.
metadata
image-quality
jpeg
rotation
kretyna oscylacyjna
źródło
źródło
Odpowiedzi:
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ą:
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.
źródło
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):
A wynik:
Następnie zapisałem obraz jako JPEG przy użyciu ustawień domyślnych:
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
):Natychmiastowe obserwacje
Używanie
cmp -l
plików, które powinny mieć identyczną treść, pozwala nam zobaczyć, gdzie różnią się pliki.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) iCOM
(komentarza) dla metadanych. WPV pozostawiaAPP0
segment nietknięty, ale z ciekawością dodaje bajt zerowy do komentarza (tak, że jest zakończony zerem ).WPV dodaje dwa
APP1
segmenty, 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:
Oto wynik:
Wyeksportowałem plik jako JPEG przy użyciu następujących ustawień:
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
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:
Są 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: AC
tabeli 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
):System operacyjny (Windows):
GIMP (Linux): 2.8.14 (z pakietu
gimp
, wersja2.8.14-1+deb8u1
)Przeglądarka zdjęć w oknie (zgodnie z metadanymi obrazu):
źródło
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:
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.
źródło
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.
źródło
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:
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ódło
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,
źródło
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?
źródło
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 :
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 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:
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:
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ść.
źródło
<?xpacket
tagach.