Před časem vyšla zprávička o novém a poněkud poťouchlém grafickém formátu FarbFeld projektu Suckless. Vývojáři slibují jednoduchý formát (ostatně definice je: 8B Magic „farbfeld“, 2B width, 2B height a následuje pole záznamů [2B2B2B2B] na pixel (RGBA) po řádcích. Toť vše. Neřeší se barevný prostor (prostě natvrdo ProPhoto RGB), neřeší se další metadata, zkrátka nic.
FarbFeld
Takže formát celkem k ničemu. Zaujalo mě ale tvrzení autorů, že data v tomto formátu prohnaná přes bzip2
dává menší soubory, než například png. Bezeztrátové formáty pro ukládání obrázků totiž počítají s tím, že ukládají bitmapový obrázek, takže se obvykle snaží jej před komprimací vhodně optimalizovat. Zkrátka využít fakt, že o daných datech něco ví. Takže onen png umí použít 5 různých bitmapových filtrů a to ještě na každý chunk jiný. Na rozdíl od bzip2
, který je stavěn na obecné datové soubory a o obrázcích neví nic.
Není nad to si věci sám vyzkoušet, takže jsem vzal vzorek 1000 obrázků ve formátu png a převedl jej do ff (FarbFeld). Následně zkomprimoval do ff.bz2. Velikosti jsou uvedeny v následující tabulce:
- Původní velikost png: 1787 MB
- Velikost ff: 17.1 GB
- Velikost ff.bz2: 1361 MB
Nekomprimované obrázky jsou dle očekávání velké, ale komprimace ff.bz2 mě překvapila, výsledek je skutečně menší.
Jenže platíme za to velkou daň v době běhu komprimace:
- Doba komprimace ff.bz2: 3136s
- Doba konverze na png: 830s
Otázkou je, zda se vyplatí čekat skoro 4x déle na o 24% menší soubory navíc uložené tak, že se s nimi prakticky nedá nic dělat (na obrázky se většinou chceme dívat, nebo je dále nějak zpracovávat). Ovšem autoři měli skutečně pravdu, obecná komprimace bz2 je skutečně výkonnější, než pro obrázky optimalizované png.
Optimalizace PNG
Tím se dostávám k dalšímu tématu. Původně jsem si myslel, že zdrojové soubory (těch 1000 png obrázků), jsou již optimalizované. Jak je uvedeno výše, png může každý chunk prohnat jedním z 5 filtrů (filtr 0 nedělá nic, takže vlastně čtyřmi filtry). Ne každé vytvořené png má skutečně nejmenší možnou velikost (některé programy si s tím příliš hlavu nelámou).
Na optimalizaci png existují různé programy, já mám ve svém obrazovém řetězci program pngcrush
. Tento program nabízí celou řadů módů, nejběžnější použití je bez parametrů, kdy program optimalizuje zadané png velmi rychle. Maximální komprese se potom dosáhne použitím parametru --brute
.
- Velikost originálních png: 1787MB
- Velikost optimalizovaných png: 1557MB
- Velikost –brute optimalizovaných png: 1552MB
Tedy původní obrázky nejsou příliš optimalizované, obyčejné pngcrush
je dokáže zmenšit o dalších 13%. Používat pngcrush --brute
nemá příliš smysl (což se ostatně píše i v dokumentaci), velikost se sníží jen o dalších 0.3%. Přičemž doba běhu brute je více než 10x delší (přes 4h oproti 1580s) než pngcrush bez parametrů.
Takže, optimalizovaná pngčka jsou jen o nějakých 14% větší než ff.bz2, zatímco čas je poloviční. A obrázky jsou na rozdíl od ff použitelné.
Technické detaily
Dávám si záležet na využití celého CPU, obvykle pro paralelní běh více procesů používám kombinaci find
a xargs
. (find ... -print0 | xargs -0 -L 1 -P 8 program
) nebo ve složitějších případech rovnou make
.
Při těchto testech jsem také s výhodou využil program parallel
:
ls -1 *.png | parallel --nice 15 pngcrush -q '{}' '{.}'.opt
Který si na rozdíl od xargu
zjistí počet cpu, umí zajistit nižší prioritu volaných procesů a také se pohodlněji pracuje se zástupnými znaky jména souborů, jména souboru bez přípony apod. Pěkné povídání o programu parallel
vyšlo před časem na ABCLinuxu.
V případě testu komprimace ff do bzip2 jsem použil variantu programu pbzip2
, která sama o sobě umí využít více cpu.
for i in *.ff ; do cat $i | pbzip2 > $i.ff.bz2 ; done
Hnidopiši jistě namítnou problematiku jmen souborů s mezerami a nutné uvozovkování, ale v tomto testy měly obrázky rozumné názvy souborů.