IO_PNG 1.2.3 をリリースしました
filter dump 対応です。
- 前回の記事
PNG は圧縮の前処理として RGB のまま圧縮するか、RGB の差分を圧縮するかの選択が画像の1行毎に出来ます。
今回追加した pngfilter.php はその行毎の filter 値を表示します。なお、結果として filter 値の数は height と一致します。
詳しくは、こちらの記事をどうぞ。(PNG filter でググって一番上にきた記事)
使い方
% composer require yoya/io_png
(略)
% php vendor/yoya/io_png/sample/pngfilter.php -f test1.png
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
% php vendor/yoya/io_png/sample/pngfilter.php -f test2.png
1 1 4 2 2 2 1 2 4 2 2 2 2 1 2 4 1 4 2 2 2 2 4 2 2 1 2 1 4 1 4 1 4 4 3 3 1 4 4 4 2 4 3 2 3 2 4 2 1 4 4 2 4 4 4 1 2 4 2 2 2 1 2 4 1 4 1 1 4 1 1 4 2 1 4 2 4 1 4 2 4 1 2 2 2 3 2 1 4 2 2 2 2 4 4 2 4 4 1 2
実験
自分の手元にある 800枚位の PNG 画像(イラスト絵)に対して実行してみました。wordhist.php はこちら >
github.com
% for f in ~/Pictures/Picture/*.png ; do php sample/pngfilter.php -f $f ; done > filter.txt
% php wordhist.php filter.txt
0 => 225389
1 => 167099
2 => 399666
3 => 14265
4 => 46279
2( Up) が多いです。
どうやらイラスト絵は上下にグラデーションをかける傾向があるようで。(手元での結果なので偏ってる可能性あり)
実装コード
https://github.com/yoya/IO_PNG/blob/1.2.3/IO/PNG.php#L294
IDAT chunk のデータ部を連結したものを丸ごと zlib 伸長して復元出来た画像の一行ごとに頭の 1byte を表示します。
$idat_inflated = gzuncompress($idat_data); (略) $stride = 1 + ceil($width * $ncomp * $bitdepth / 8); $offset = 0; for ($y = 0 ; $y < $height ; $y++) { $filter = ord(substr($idat_inflated, $offset, 1)); $offset += $stride; echo "$filter "; }
ceil で妙な事をしてるのは、grayscale と palette 形式では、 1, 2, 4 bit 深度が表現出来て、バイトのキリの良いとこで終わらない可能性があるからです。