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.