Dlaczego te (bezstratne) metody kompresji wielu podobnych obrazów png są nieskuteczne?

21

Właśnie natrafiłem na następującą rzecz: umieściłem wiele identycznych kopii obrazu png w folderze, a następnie próbowałem skompresować ten folder za pomocą następujących metod:

  • tar czf folder.tar.gz folder/
  • tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz (ten działa dobrze dla identycznych obrazów, jednak dla podobnych obrazów zysk wynosi zero)
  • zip -r folder.zip folder/

Kiedy sprawdził wielkość .tar.gz, .tar.xz, .zipzdałem sobie sprawę, że to jest prawie taki sam, jak jeden z folder/.
Rozumiem, że sam obraz png może mieć wysoki poziom kompresji i dlatego nie może być dalej kompresowany. Jednak podczas łączenia wielu podobnych (w tym przypadku nawet identycznych) obrazów png do archiwum, a następnie kompresji archiwum, oczekiwałbym znacznego zmniejszenia wymaganego rozmiaru. W przypadku identycznych obrazów spodziewałbym się rozmiaru mniej więcej wielkości pojedynczego obrazu.

gość
źródło
2
To zachowanie występuje tylko w przypadku plików png?
pdexter
7
Nie czyniąc z tego odpowiedzi, ponieważ odpowiada na niezadane pytanie, ale jeśli wiesz, że będziesz kompresował wiele prawie identycznych obrazów, zawsze możesz zastąpić wszystkie obrazy, z wyjątkiem pierwszego, różnicą binarną względem pierwszego obrazu. Zakładając, że obraz nie jest zaszumiony, skończysz z bardzo kompresowalnymi wyjściami, a oryginalne obrazy nadal będą odtwarzalne.
Baldrickk
Jeśli używasz nieskompresowanych plików (np. .bmp), Plik tar.gz powinien móc skorzystać z podobieństwa. (Przynajmniej jeśli podobieństwo jest identyczne z wieloma pikselami)
CodesInChaos
1
Nic o tym nie wiem, ale według Wikipedii format archiwum „ZPAQ” obsługuje deduplikację, która moim zdaniem jest tym, czego szukasz. en.wikipedia.org/wiki/ZPAQ#Deduplication
coneslayer
Próbujesz skompresować coś, co już zostało skompresowane. Zobacz tutaj
Kyle Khalaf,

Odpowiedzi:

34

Zobacz, jak działają algorytmy kompresji. Przynajmniej te z rodziny Lempel-Ziv ( gzip używa LZ77 , zipnajwyraźniej też tak robi i xz używa LZMA ) kompresują nieco lokalnie : Podobieństw, które leżą daleko od siebie, nie można zidentyfikować.

Szczegóły różnią się między metodami, ale sedno jest takie, że zanim algorytm osiągnie drugi obraz, już „zapomniał” początek pierwszego. I tak dalej.

Możesz spróbować ręcznie zmienić parametry metody kompresji; jeśli rozmiar okna (LZ77) lub. rozmiar bloku / porcji (późniejsze metody) jest co najmniej tak duży jak dwa obrazy, prawdopodobnie zobaczysz dalszą kompresję.


Zauważ, że powyższe tak naprawdę ma zastosowanie tylko wtedy, gdy masz identyczne obrazy lub prawie identyczne obrazy nieskompresowane . Jeśli występują różnice, skompresowane obrazy mogą nie wyglądać podobnie w pamięci. Nie wiem, jak działa kompresja PNG; możesz ręcznie sprawdzić reprezentacje szesnastkowe obrazów dla udostępnionych podłańcuchów.

Pamiętaj również, że nawet przy zmienionych parametrach i nadmiarowości do wykorzystania, nie sprowadzisz się do rozmiaru jednego obrazu. Większe słowniki oznaczają większy rozmiar słowa kodowego, a nawet jeśli dwa obrazy są dokładnie identyczne, może być konieczne zakodowanie drugiego za pomocą wielu słów kodowych (które wskazują na pierwsze).

Raphael
źródło
3
Dokładniejsza odpowiedź: gzip i zip używają tego samego podstawowego kodeka DEFLATE, który jest oparty na teorii LZ77 + Huffmana.
Nayuki,
Tak! To połowa historii; zobacz moją odpowiedź dla drugiej połowy lub świetną odpowiedź Nayuki .
DW
1
dla potomnych: Archiwum formatach, które eksploatują zwolnień wśród plików przez połączenie plików w jeden blob i sprężania , które określane są jako stałe . nie jestem pewien, czy istnieją inne warunki dla pośrednich poziomów „solidności” itp.
underscore_d
22

Dlaczego tak się dzieje. W rzeczywistości występują tutaj dwa różne efekty:

  • Każdy plik jest kompresowany niezależnie. Niektóre programy do archiwizacji - w tym zip - kompresują każdy plik niezależnie, bez pamięci z jednego pliku do drugiego. Innymi słowy, każdy plik jest osobno kompresowany, a następnie skompresowane pliki są łączone w archiwum.

  • Pamięć krótkotrwała. Niektóre programy do archiwizacji mogą wykorzystywać informacje o jednym pliku, aby lepiej skompresować następny plik. Skutecznie łączą pliki, a następnie kompresują wynik. To jest poprawa.

    Zobacz także odpowiedź Nayuki, aby uzyskać więcej informacji na ten temat.

    Istnieje jednak drugi problem. Niektóre schematy kompresji - w tym zip, gzip i bzip2 - mają ograniczoną pamięć. Kompresują dane w locie i zapamiętują ostatnie 32 KB danych, ale nie pamiętają nic o danych, które pojawiły się znacznie wcześniej w pliku. Innymi słowy, nie mogą znaleźć zduplikowanych danych, jeśli duplikaty występują dalej niż 32 KB od siebie. W rezultacie, jeśli identyczne pliki są krótkie (krótsze niż około 32 KB), algorytm kompresji może usunąć zduplikowane dane, ale jeśli identyczne pliki są długie, algorytm kompresji zostaje ukryty i staje się bezwartościowy: nie może wykryć żadnego z duplikat danych. (Bzip pamięta dane z ostatnich 900 KB lub więcej, zamiast 32 KB).

    Wszystkie standardowe algorytmy kompresji mają pewien maksymalny rozmiar pamięci, poza którym nie wykrywają wzorców ... ale dla niektórych liczba ta jest znacznie większa niż dla innych. W przypadku Bzip jest to coś w rodzaju 900 KB. W przypadku XZ jest to coś w rodzaju 8 MB (z ustawieniami domyślnymi). W przypadku 7z jest to coś w rodzaju 2 GB. 2 GB jest więcej niż wystarczająco duże, aby rozpoznać zduplikowane kopie plików PNG (które zwykle są znacznie mniejsze niż 2 GB). Ponadto 7z stara się również sprytnie podchodzić do umieszczania w archiwum plików, które prawdopodobnie będą do siebie podobne, aby pomóc kompresorowi w pracy; tar nie wie o tym nic.

    Zobacz także odpowiedź Rafaela i odpowiedź Nayuki za uzyskać więcej wyjaśnienie tego efektu.

Jak to dotyczy twojego ustawienia. W twoim konkretnym przykładzie pracujesz z obrazami PNG. Obrazy PNG są kompresowane, więc każdy plik PNG można traktować jako sekwencję losowo wyglądających bajtów, bez żadnych wzorców lub duplikacji w pliku. Kompresor nie ma nic do wykorzystania, jeśli patrzy na pojedynczy obraz PNG. Dlatego jeśli spróbujesz skompresować pojedynczy plik PNG (lub utworzysz archiwum zip / tar / ... zawierające tylko jeden plik PNG), nie uzyskasz żadnej kompresji.

Teraz spójrzmy na to, co się stanie, jeśli spróbujesz przechowywać wiele kopii tego samego pliku PNG:

  • Małe pliki Jeśli plik PNG jest bardzo mały, wszystko oprócz zip będzie działało świetnie. Zip zawiedzie spektakularnie: kompresuje każdy plik niezależnie, więc nie ma szansy wykryć nadmiarowości / duplikacji plików. Ponadto, gdy próbuje skompresować każdy plik PNG, nie osiąga żadnej kompresji; rozmiar archiwum zip będzie ogromny. Natomiast rozmiar archiwum tar (skompresowanego za pomocą gzip, bzip2 lub xz) i archiwum 7z będzie małe, ponieważ zasadniczo przechowuje jedną kopię pliku, a następnie zauważa, że ​​wszystkie pozostałe są identyczne - korzyści z zachowywania pamięci z jednego pliku do drugiego.

  • Duże pliki. Jeśli plik PNG jest duży, tylko 7z działa dobrze. W szczególności zip nadal spektakularnie zawodzi. Ponadto pliki tar.zip i tar.bzip2 nie działają poprawnie, ponieważ rozmiar pliku jest większy niż okno pamięci kompresora: gdy kompresor widzi pierwszą kopię pliku, nie może go zmniejszyć (ponieważ został już skompresowany ); zanim zacznie widzieć początek drugiej kopii pliku, zapomniał już o sekwencjach bajtów widocznych na początku pierwszego pliku i nie może nawiązać połączenia, że ​​te dane są w rzeczywistości duplikatem.

    Natomiast tar.xz i 7z nadal świetnie sobie radzą z wieloma kopiami dużego pliku PNG. Nie mają ograniczenia „małego rozmiaru pamięci” i są w stanie zauważyć, że druga kopia pliku jest identyczna z pierwszą kopią, więc nie ma potrzeby przechowywania jej po raz drugi.

Co możesz na to poradzić. Użyj 7z. Ma kilka heurystyk, które pomogą wykryć identyczne lub podobne pliki i kompresować naprawdę dobrze w tym przypadku. Możesz także spojrzeć na lrzip z kompresją lzop.

Skąd mam wiedzieć? Udało mi się to zweryfikować, przeprowadzając eksperymenty ze 100 kopiami pliku zawierającego losowe bajty. Próbowałem 100 kopii pliku 4KB, 100 kopii pliku 1 MB i 100 kopii pliku 16 MB. Oto, co znalazłem:

Size of file      Size of compressed archive (with 100 copies)
                  zip  tar.gz  tar.bz2  tar.xz    7z
         4KB    414KB     8KB     10KB     5KB    5KB
         1MB    101MB   101MB    101MB     1MB    2MB
        16MB    1.6G    1.6GB    1.6GB   1.6GB  401MB

Jak widać, zip jest okropny bez względu na to, jak mały jest twój plik. 7z i xz są dobre, jeśli twoje obrazy nie są zbyt duże (ale xz będzie kruchy i zależy od kolejności umieszczania obrazów w archiwum, jeśli masz kilka duplikatów i niektóre nie-duplikaty zmieszane razem). 7z jest naprawdę dobry, nawet w przypadku dużych plików.

Bibliografia. Jest to również dobrze wyjaśnione w wielu postach na Super User. Spójrz:

DW
źródło
5
Warto również pamiętać, że format ZIP został zaprojektowany około 1990 roku (PKZIP wprowadził format ZIP w 1989 roku, mówi Wikipedia, a DEFLATE został wprowadzony w 1993 roku). W tym okresie dość powszechnym komputerem mógł być komputer 286 lub 386 (486 został wprowadzony w 1989 roku, ale jak zwykle zajęło trochę czasu) z systemem DOS z może 2-4 MB pamięci RAM, tylko może 400- 500 KB, z których można było bezpośrednio korzystać bez inteligentnego programowania (EMS, XMS), dla których nie można zagwarantować dostępności. W tym środowisku mały rozmiar okna kompresji był prawie wymagany.
CVn
„Każdy plik skompresowany niezależnie” - Wygląda na to, że różnią się znacznie między standardami i narzędziami. Moje doświadczenie z domyślnym oprogramowaniem do pakowania Ubuntu polega na tym, że wydaje się, że dekompresuje wszystko podczas otwierania archiwum. Często myślałem, że powinien kompresować każdy plik niezależnie, ponieważ wzrost użyteczności zwykle przewyższa wady kompresji.
Raphael
„100 kopii pliku zawierającego losowe bajty” - co z „podobnymi” plikami? (W kierunku rzeczywistego pytania, jak podobne pliki PNG podobnych obrazów?)
Raphael
Raphael dobrze to ujął w swojej odpowiedzi. W rzeczywistości mam wiele podobnych (nie identycznych) obrazów, które chcę przechowywać. Podobne pod względem wykazują tę samą strukturę z niewielkimi zmianami (również pod względem intensywności i tła). Różnice są jednak tak małe, że są ledwo widoczne. Próbowałem tarje, a następnie kompresowałem xz(co działało bardzo dobrze dla identycznych obrazów), jednak w przypadku podobnych obrazów wzmocnienie wynosi zero. Próbowałem z 71 obrazami o rozmiarze ~ 831 KB.
a_guest
2
@ a_guest - to nie pójdzie dobrze. Podobnie wyglądające obrazy PNG będą miały bardzo różną zawartość bajtów (z powodu kompresji PNG). Zobacz także superuser.com/q/730592/93541 , superuser.com/q/418286/93541 , superuser.com/q/893206/93541 , superuser.com/q/921140/93541 - w zasadzie nie ma dobrych rozwiązań.
DW
10

Po pierwsze, zauważ, że format obrazu PNG to zasadniczo surowe piksele RGB (z pewnym filtrowaniem światła) przepchnięte przez format kompresji DEFLATE. Ogólnie rzecz biorąc, skompresowane pliki (PNG, JPEG, MP3 itp.) Nie zobaczą żadnej korzyści z ponownej kompresji. Dlatego ze względów praktycznych możemy traktować plik PNG jako nieściśliwe losowe dane do końca eksperymentu.

Po drugie, zauważ, że formaty ZIP i gzip również używają kodeka DEFLATE. (To by wyjaśniało, dlaczego skompresowanie pojedynczego pliku w porównaniu do gzipa spowoduje zasadniczo taki sam rozmiar wyjściowy).


Teraz pozwól mi skomentować każdy przypadek testowy indywidualnie:

  • tar czf folder.tar.gz folder/

    Spowoduje to utworzenie (nieskompresowanego) pliku TAR, który połączy wszystkie identyczne pliki PNG (z niewielką ilością metadanych i dopełnienia). Następnie ten pojedynczy plik jest przesyłany przez kompresor gzip w celu utworzenia jednego skompresowanego pliku wyjściowego.

    Niestety format DEFLATE obsługuje tylko okno słownika LZ77 o wielkości 32768 bajtów. Więc nawet jeśli plik TAR zawiera powtarzalne dane, jeśli plik PNG jest większy niż 32 KiB, to na pewno kompresor DEFLATE nie może zapamiętać danych wystarczająco daleko, aby skorzystać z faktu, że powtarzają się identyczne dane.

    Z drugiej strony, jeśli powtórzysz eksperyment z, powiedzmy, 20-KB pliku PNG zduplikowanym 10 razy, bardzo prawdopodobne jest, że otrzymasz plik gzip tylko nieco większy niż 20 KB.

  • tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz

    Spowoduje to utworzenie pliku TAR, tak jak poprzednio, a następnie użycie formatu xz i kompresora LZMA / LZMA2. W tej sytuacji nie mogłem znaleźć informacji o LZMA, ale z 7-Zip dla Windows wiem, że może on obsługiwać duże okna wielkości słownika (np. 64 MiB). Możliwe więc, że korzystałeś z nieoptymalnych ustawień i że kodek LZMA mógł zmniejszyć plik TAR do rozmiaru jednego pliku PNG.

  • zip -r folder.zip folder/

    Format ZIP nie obsługuje „stałych” archiwów; to znaczy każdy plik jest kompresowany niezależnie. Zakładamy, że każdy plik jest nieściśliwy. Dlatego nie można wykorzystać faktu, że każdy plik jest identyczny, a plik ZIP będzie tak duży, jak zwykła konkatenacja wszystkich plików.

Nayuki
źródło
xzdomyślnie działa w xz -6trybie, który korzysta ze słownika LZMA2 8 MiB . Nie mogłem od razu znaleźć na stronie man dostępnej w moim systemie Debian, jaki jest domyślny rozmiar okna dla kompresora.
CVn
Dobra odpowiedź! W drugim przypadku tak naprawdę robiłem: tar czf folder.tar.gz folder/ && xz --stdout folder.tar.gz > folder.tar.gz.xzbez żadnego efektu (co ma sens zgodnie z tym, co wyjaśniłeś). Wydaje mi się, że trochę się zagubiłem w tych kompresjach: D Podczas używania tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xzfaktycznie uzyskuję nieco więcej niż rozmiar jednego obrazu (co również ma sens zgodnie z domyślnym rozmiarem okna dict 64 MiB). Zaktualizowałem odpowiednio moje pytanie. Dzięki!
a_guest
@ a_guest OK, więc twój komentarz opisuje inną drugą sprawę. Problem polega na tym tar -> gzip -> xz, że gzip DEFLATE może kompresować każdą kopię danych PNG w inny sposób, więc xz nie będzie w stanie wykryć redundancji.
Nayuki,
6

Problem polega na tym, że (większości) schematom kompresji brakuje wiedzy na temat posiadanych danych. Nawet jeśli zdekompresujesz swoje pliki PNG do map bitowych i skompresujesz je w archiwum, nie uzyskasz (znacząco) mniejszych wyników.

W przypadku wielu podobnych obrazów odpowiednim schematem kompresji byłby kodek wideo.

Używając bezstratnego kodowania, powinieneś osiągnąć prawie idealny wynik kompresji, którego oczekujesz.

Jeśli chcesz to przetestować, użyj czegoś takiego:

ffmpeg -i img%03d.png -c:v libx264 -c:v libx264 -profile:v high444 -crf 0 out.mp4

https://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images

Jonas
źródło
Dobry punkt za pomocą kodera wideo! Wypróbuję to, kiedy zaktualizuję moje Ubuntu, ponieważ 14.04 domyślnie nie zawiera ffmpeg. Myślę, że ten koder wideo używa bezstratnej kompresji, a przynajmniej ma do tego przełącznik? Czy wiesz?
a_guest
Tak, -crf 0 sprawia, że ​​jest bezstratny (lub jak wspomniano w dokumentach -qp 0 robi to samo (preferowane jest -qp 0)). trac.ffmpeg.org/wiki/Encode/H.264
Jonas
4

PNG to kombinacja filtrów + LZ77 + Huffman (połączenie LZ77 + Huffman nazywa się Deflate) w następującej kolejności:

krok 1) jeśli filtr różni się od Brak, wartość pikseli jest zastępowana różnicą w stosunku do sąsiednich pikseli (więcej szczegółów patrz http://www.libpng.org/pub/png/book/chapter09.html ) . Zwiększa to kompresję obrazów z gradientami (więc ... 4 5 6 7 staje się ... 1 1 1 1) i może pomóc w obszarach tego samego koloru (... 3 3 3 5 5 5 5 5 staje się 0 0 0 2 0 0 0 0 0). Domyślnie filtry są włączone w obrazach 24-bitowych i wyłączone w obrazach 8-bitowych z paletą.

krok 2) dane są kompresowane za pomocą LZ77, który zastępuje powtarzające się (pasujące) ciągi bajtów krotką zawierającą odległość do dopasowania i długość dopasowania.

krok 3) wynik kroku 2 jest kodowany kodem Huffmana, który zastępuje symbole o stałej długości kodami o zmiennej długości, im częściej symbol, tym krótszy kod.

Istnieje wiele problemów:

Mała zmiana, która wpływa na kilka pikseli, spowoduje zmiany wyników z 3 kroków kompresji png:

1) Filtrowana wartość sąsiednich pikseli ulegnie zmianie (w zależności od zastosowanego filtra). To wzmocni efekty małych zmian.

2) Zmiana oznacza, że ​​dopasowania do tego obszaru będą się różnić. Na przykład zmiana 333333 na 333533 powoduje, że kolejne wystąpienie 333333 nie będzie już zgodne, więc wybierze kolejne dopasowanie do 333333 z inną odległością lub wybierze to samo dopasowanie, ale o krótszej długości, a następnie kolejne dopasowanie dla ostatnich 3 bajtów. Samo to bardzo zmieni wyniki.

3) Największym problemem jest krok 3. Kod huffmana używa zmiennej liczby bitów, więc nawet niewielka zmiana spowoduje, że wszystko, co następuje, nie będzie już wyrównane. AFAIK Większość algorytmów kompresji nie może wykryć dopasowań, które nie są wyrównane bajtowo, więc zapobiegnie (lub przynajmniej znacznie zmniejszy) kompresję już skompresowanych danych, które następuje po zmianie, chyba że kompresor wykryje dopasowania, które nie są wyrównane bajtowo.

Inne problemy są już objęte innymi odpowiedziami:

4) Gzip używa tego samego algorytmu Deflate ze słownikiem 32 KB, więc jeśli pliki png są większe niż 32 KB, dopasowania nie zostaną wykryte, nawet jeśli są identyczne. Bzip2 jest lepszy pod tym względem, ponieważ używa bloku 900 KB. XZ używa LZMA, którego IIRC ma słownik o wielkości 4 MB w domyślnym poziomie kompresji. 5) Format zip nie używa stałej kompresji, więc nie będzie lepiej kompresował podobnych lub identycznych plików.

Być może kompresory z rodziny PAQ lub PPMD ​​będą kompresować lepiej, ale jeśli potrzebujesz skompresować wiele podobnych plików obrazów, możesz rozważyć 3 podejścia:

1) Przechowuj obrazy nieskompresowane (z PNG -0 lub w formacie bez kompresji) i kompresuj za pomocą kompresora z dużym słownikiem lub rozmiarem bloku. (LZMA będzie działać dobrze)

2) Inną opcją byłoby zachowanie filtrów, ale usunięcie kompresji Deflate z plików PNG. Można to zrobić na przykład za pomocą narzędzia ( AdvDef ). Następnie kompresujesz powstałe nieskompresowane pliki PNG. Po dekompresji możesz zachować nieskompresowany plik PNG lub skompresować go ponownie za pomocą AdvDef (ale zajmie to trochę czasu).

Musisz przetestować oba podejścia, aby zobaczyć, który kompresuje najbardziej.

3) Ostatnią opcją byłoby konwersja obrazów png w wideo, skompresowanie go za pomocą bezstratnego kompresora wideo, takiego jak x264 bezstratny (zwracając szczególną uwagę na użycie odpowiedniego formatu kolorów), a następnie po ekstrakcji wyodrębnij ramki do poszczególnych obrazów png. Można to zrobić za pomocą ffmpeg. Trzeba też zachować mapowanie między numerem klatki a oryginalną nazwą.

To byłoby najbardziej złożone podejście, ale jeśli wszystkie PNG są częścią animacji, może być najbardziej skuteczne. Jednak potrzebny będzie format wideo obsługujący przezroczystość, jeśli jest potrzebny.

Edycja: Istnieje również format MNG, który nie byłby często używany.

ggf31416
źródło
2

Kiedy masz specjalne zestawy danych, używasz specjalnych algorytmów, a nie narzędzi wielofunkcyjnych.

Odpowiedź jest taka, że ​​wybrane przez ciebie bezstratne kompresje nie są wykonane do tego, co robisz. Nikt nie oczekuje, że dwukrotnie skompresujesz ten sam obraz, a nawet jeśli to zrobisz (przypadkowo) sprawdzenie wszystkich poprzednich danych wejściowych sprawiłoby, że Twój algorytm O (n ^ 2) (może trochę lepiej, ale przynajmniej naiwne podejście byłoby n ^ 2).

Większość programów do kompresji, które testowałeś podczas pracy w O (n), podkreślają prędkość w stosunku do optymalnego współczynnika kompresji. Nikt nie chce uruchamiać swojego komputera przez 5 godzin, aby zaoszczędzić kilka MB, szczególnie w dzisiejszych czasach. Przy większych wejściach cokolwiek powyżej O (n) staje się kwestią czasu działania.

Inną kwestią jest baran. Nie możesz uzyskać dostępu do każdej części danych wejściowych w dowolnym momencie, gdy dane wejściowe stają się wystarczająco duże. Nawet nie zważając na to, większość ludzi nie chce rezygnować z całego pamięci RAM lub procesora, aby coś skompresować.

Jeśli masz w plikach wzorce, które chcesz skompresować, będziesz musiał wykonać na nich operacje manuel, napisać własną kompresję lub potencjalnie użyć kompresji typu „archiwum” (nano). Kompresja do długotrwałego przechowywania, która jest zbyt wolna do codziennego użytku.

Inną opcją może być bezstratna kompresja wideo.

Mam nadzieję, że jest pomocna
źródło
1
Biorąc pod uwagę, że struktury katalogów często zawierają wiele identycznych plików w różnych miejscach, wydaje się, że dobre narzędzie w stylu zip powinno zapewniać opcję sprawdzenia, czy plik dodawany do archiwum ma skompresowane / nieskompresowane wartości i rozmiary skrótów które pasują do istniejącego pliku. Jeśli oba skróty i oba rozmiary są takie same, warto dołączyć drugą nazwę do bloku danych powiązanego z pierwszym plikiem. Nawet jeśli ZIP nie może tego pomieścić, wydaje się użyteczną funkcją w przyszłych formatach.
supercat
1
Twoja odpowiedź sugeruje, że algorytm kompresji tar jest dobry do kompresji niektórych rodzajów nadmiarowości, ale nie do tego, który występuje w scenariuszu PO. Może chcesz opisać jakie rodzaje redundancji uważasz, że to jest dobre dla, ponieważ to nie jest wcale oczywiste. Dla kogoś, kto być może nigdy nie używał tego kompresora, widzą tylko, że wypróbowali go na czymś, co teoretycznie jest dość kompresowalne, to nie działało, więc do czego, do cholery, ta kompresor jest dobra?
Don Hatch,
1
@leftaroundabout: W żadnym znanym mi Uniksie nie ma możliwości użycia semantyki „kopiuj przy zapisie” z dopasowanymi plikami. W wielu przypadkach istnieją nadmiarowe kopie, aby poradzić sobie z faktem, że rzeczy, które mogą być takie same dzisiaj, jutro mogą nie być takie same, i w takich przypadkach nie wydaje się, aby odpowiednie dowiązania symboliczne lub dowiązania twarde były odpowiednie.
supercat
1
@ superuper: w przypadku wielu takich plików jest to całkowicie dobre rozwiązanie, aby użyć dowiązania symbolicznego do jednej „oficjalnej” wersji tylko do odczytu. Jeśli chcesz zmienić kopię, zastąp dowiązanie symboliczne kopią fizyczną.
leftaroundabout
1
@leftaroundabout: Jedną rzeczą, którą czasami uważałem za interesującą, gdyby można zmniejszyć niebezpieczeństwo inżynieryjnych kolizji skrótu do akceptowalnego poziomu, byłoby posiadanie uniwersalnego identyfikatora referencyjnego opartego na haszowaniu, tak aby zamiast symbolicznego linkowania do „logicznej” nazwy pliku można by utworzyć link na podstawie skrótu. Archiwa przechowywałyby wówczas około 256 bajtów skrótu zamiast przechowywać naprawdę duże pliki. Odmiana takiego podejścia może być również wykorzystana, aby umożliwić buforowanie plików, które należało zabezpieczyć przed zmianami.
supercat
2

Format pliku PNG korzysta już wewnętrznie z algorytmu kompresji DEFLATE. Jest to ten sam algorytm, którego używają xz, gzip i zip - tylko w niektórych odmianach. tar.gzi tar.xzskorzystaj z podobieństwa między plikami, co zipnie.

Tak więc faktycznie kompresujesz DEFLATE w stosunku do skompresowanych plików DEFLATE - dlatego pliki zachowują prawie oryginalny rozmiar.

bzip2Programu (także powiązany algorytm) jest lepszy jeśli chodzi o (prawie) identycznych plików.

# for i in $(seq 4); do cp test.png test$i.png; done
# tar -cjf archive.tar.bz2 *.png
# ls -l
-rw-r--r-- 1 abcde users  43813 15. Jul 08:45 test.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:45 test1.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test2.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test3.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test4.png
-rw-r--r-- 1 abcde users  68115 15. Jul 08:47 archive.tar.bz2
rexkogitans
źródło
PNG - pamiętaj, że są używane filtry, niestandardowa deflacja (który z nich jest zresztą standardowy?) I masz rację, że dwukrotne uruchomienie tego samego algorytmu nic nie daje (a przynajmniej nie powinno być korzystne), ale uruchomienie nie ma gwarancji, że ten sam algorytm z różnymi ustawieniami zawiedzie. Istnieją również różnice między deflate32, deflate64, LZW, LZMA, nie można po prostu powiedzieć, że wszystkie używają tej samej deflacji.
Zły
Dlatego powiedziałem „w niektórych odmianach”. Oczywiście DEFLATE odnosi się raczej do pewnego rodzaju algorytmu niż do określonej implementacji.
rexkogitans
3
Nie rozumiem tego, co rozumiem. Tak, jeden sam plik PNG jest już skompresowany, więc nie można oczekiwać dalszej kompresji jakichkolwiek mieć większego wpływu. Można jednak oczekiwać, że połączenie kilku identycznych plików PNG (co w zasadzie jest tutaj sytuacją) zmniejszy się do niewiele większego niż jeden z nich.
Don Hatch
Oczywiście te algorytmy kompresji pomijają ten punkt. bzip2łapie go: tar -cjf archive.tar.bz2 *.png. Zaktualizowano w mojej odpowiedzi.
rexkogitans