Edited at

ImageMagick の PNG オプション

ImageMagick の PNG を処理するオプションを解説するエントリです。


-quality <Q>

JPEG と全然仕組みは違いますが、PNG にも quality オプションがあります。

10の桁と1の桁を分けて使います。ちなみにデフォルト75です。

あと、これはイケてないのですが内部的にデフォルト初期値が 0 な為に 0 や 00 も 75 扱いになります。。


  • 10 の桁

0 (または省略)
Z_HUFFMAN_ONLY strategy、 zlib デフォルト圧縮レベル

1-9
zlib の圧縮レベル


  • 1 の桁

0-4
PNG フィルタメソッド

5
圧縮レベル > 5 の時、libpng adaptive フィルタ
圧縮レベル <= 5 又はグレースケールやパレットの時はフィルタ無し。

6
libpng adaptive フィルタ

7
MNG出力では"LOCO" フィルタ(intrapixel differing)
でなければフィルタ無し。IM-6.7.0-9 以前では機能しない

8
Z_RLE strategy ( quality < 10 だと Z_HUFFMAN_ONLY) adaptive フィルタ。 IM-6.7.0-10 以前では 6 扱い

9
Z_RLE strategy ( quality < 10 だと Z_HUFFMAN_ONLY), PNG フィルタ 無し。IM-6.7.0-10 以前では 6 扱い

参考までに 10の桁と 1 の桁を変えての実行結果。

% for q in `seq 0 1 9` ;

do convert fujisan.png -quality ${q}0 fujisan-${q}0.png ;
done
% ls -l fujisan-??.png
-rw-r--r-- 1 yoya staff 11136998 12 13 22:57 fujisan-00.png
-rw-r--r-- 1 yoya staff 12291141 12 13 22:57 fujisan-10.png
-rw-r--r-- 1 yoya staff 12067045 12 13 22:57 fujisan-20.png
-rw-r--r-- 1 yoya staff 11658367 12 13 22:57 fujisan-30.png
-rw-r--r-- 1 yoya staff 12004722 12 13 22:57 fujisan-40.png
-rw-r--r-- 1 yoya staff 11678218 12 13 22:57 fujisan-50.png
-rw-r--r-- 1 yoya staff 11277910 12 13 22:57 fujisan-60.png
-rw-r--r-- 1 yoya staff 11136998 12 13 22:57 fujisan-70.png
-rw-r--r-- 1 yoya staff 10973235 12 13 22:57 fujisan-80.png
-rw-r--r-- 1 yoya staff 10936107 12 13 22:57 fujisan-90.png

% for q in `seq 0 1 9` ;

do convert fujisan.png -quality 0${q} fujisan-0${q}.png ;
done
% ls -l fujisan-??.png
-rw-r--r-- 1 yoya staff 11136998 12 13 22:59 fujisan-00.png
-rw-r--r-- 1 yoya staff 30001632 12 13 22:59 fujisan-01.png
-rw-r--r-- 1 yoya staff 30001632 12 13 22:59 fujisan-02.png
-rw-r--r-- 1 yoya staff 30001632 12 13 22:59 fujisan-03.png
-rw-r--r-- 1 yoya staff 30001632 12 13 22:59 fujisan-04.png
-rw-r--r-- 1 yoya staff 14194478 12 13 22:59 fujisan-05.png
-rw-r--r-- 1 yoya staff 14194478 12 13 22:59 fujisan-06.png
-rw-r--r-- 1 yoya staff 14194478 12 13 22:59 fujisan-07.png
-rw-r--r-- 1 yoya staff 14194478 12 13 22:59 fujisan-08.png
-rw-r--r-- 1 yoya staff 14194478 12 13 22:59 fujisan-09.png

quality のデフォルトは 75 で、それより 90 の方がサイズが少し減っていますが、その代わり処理時間が数倍になります。

% /usr/bin/time convert fujisan.png -quality 75 fujisan-75.png

4.67 real 4.41 user 0.20 sys
% /usr/bin/time convert fujisan.png -quality 90 fujisan-90.png
12.20 real 11.78 user 0.25 sys
% ls -l fujisan-75.png fujisan-90.png
-rw-r--r-- 1 yoya staff 11136998 12 14 01:31 fujisan-75.png
-rw-r--r-- 1 yoya staff 10936107 12 14 01:31 fujisan-90.png


-comment

任意のコメントをつけられます。

% convert -comment "This is a rose." rose: rose-comment.png

% identify -verbose rose-comment.png | grep -i comment
Image: rose-comment.png
comment: This is a rose.


-define png:


png:color-type

PNG はグレー画像、パレット画像、フルカラー画像、そして各々に透明度をつける組み合わせで、カラータイプを持ち、タイプに応じたピクセル形式でファイルに保存します。


  • カラータイプ一覧

Color Type
Bit Depth
Interpretation

0 png-pixel-type0.png

1,2,4,8,16
グレースケール.

2 png-pixel-type2.png

8,16
RGB の3つ組. (PNG24,PNG48)

3png-pixel-type3.png

1,2,4,8
パレットへのインデックス値。PLTE チャンクが必須。(PNG8)

4 png-pixel-type4.png

8,16
グレースケールの各ピクセルにアルファ値が続く。いわゆる YA 形式.

6 png-pixel-type6.png

8,16
RGBAの4つ組、A はアルファ値. (PNG32,PNG64)

出力PNGのカラータイプを指定できます。

ちなみに互換性のないカラータイプには変換できません。

例えば、color-type 2 の RGB 画像 fujisann.png を用意して、

% identify -verbose fujisan.png | grep color_type

png:IHDR.color_type: 2 (Truecolor)

RGB から color-type:2(RGB) と 6(RGBA) には変換出来ます。

% convert fujisan.png -define png:color-type=2  2.png

% convert fujisan.png -define png:color-type=6 6.png
%

しかし、それ以外の値 color-type:0(Grayscale) 3(Palette), 4(Grayscale+Alpha) を指定するとエラーになります。

% convert fujisan.png -define png:color-type=0  0.png

convert: Cannot write image with defined png:bit-depth or png:color-type. `0.png' @ warning/png.c/MagickPNGWarningHandler/1744.
% convert fujisan.png -define png:color-type=3 3.png
convert: Cannot write PNG8 or color-type 3; colormap is NULL `3.png' @ error/png.c/WriteOnePNGImage/9752.
% convert fujisan.png -define png:color-type=4 4.png
convert: Cannot write image with defined png:bit-depth or png:color-type. `4.png' @ warning/png.c/MagickPNGWarningHandler/1744.

グレースケールなら -colorspace Gray 。パレットなら -type Palette で変換して下さい。

% convert fujisan.png -colorspace Gray -define png:color-type=0  0.png

% convert fujisan.png -type Palette -define png:color-type=3 3.png
% convert fujisan.png -colorspace Gray -define png:color-type=4 4.png


png:bit-depth

R,G,B 各々に多くの場合 8bit (0〜255)で格納しますが、このビット数を変更できます。

% convert fujisan.png -define png:bit-depth=16 fujisan-q16.png

% identify fujisan.png fujisan-q16.png
fujisan.png PNG 4240x2832 4240x2832+0+0 8-bit sRGB 10.6617MiB 0.000u 0:00.000
fujisan-q16.png PNG 4240x2832 4240x2832+0+0 16-bit sRGB 12.6534MiB 0.000u 0:00.000

ただし、上記のカラータイプ一覧にある通り、カラータイプ毎に使える bit-depth が制限される事に注意です。

% convert fujisan.png -define png:bit-depth=4 fujisan-q4.png

convert: Cannot write image with defined png:bit-depth or png:color-type. `fujisan-q4.png' @ warning/png.c/MagickPNGWarningHandler/1744.


png:compression-filter

PNG は zlib 圧縮がよく効くようRGBデータ表現を少しいじるフィルタの仕組みがあり、その具体的な指定ができます。

範囲は 0〜9です。


  • 0: 未指定。つまり quality の指示に準ずる。

  • 1〜4: 0〜3 にずらしてフィルタタイプを明示的に選択できます。libpng の定義で 0:NONE, 1:SUB, 2:UP, 3:AVG

  • 5: 適応フィルタ(全部試して良いのを選択する) カラーマップは例外

  • 6: 適応フィルタ。カラーマップも含める。

  • 7: MNG LOCO 圧縮 (アニメーションのコマ間の差分圧縮)

  • 8: 適応フィルタ + Z_RLE ストラテジ

  • 9: フィルタなしの Z_RLE ストラテジ

例えば綺麗なグラデーション画像の場合、隣のピクセル色との差分で表現すれば、全部同じ値になって圧縮率がめちゃくちゃ上がる。なんて事も極端な例としては有り得ます。上記の例だと 1:SUB がそれに相当します。


png:compression-level

zlib の圧縮は時間をかけた方がよりサイズを減らせるので、その頑張り具合を指定できます。

範囲は 0〜9 です。0 は速いけど圧縮があまり効かない。9 は遅いけどかなり圧縮されます。


png:compression-strategy

zlib 圧縮はランレングスとハフマン圧縮を組み合わせたアルゴリズムで、例えばハフマン圧縮だけ使う。みたいな指定が出来ます。範囲は 0〜4 です。


  • 0: 未指定。つまり quality の指示に準ず

  • 1: FILTERED

  • 2: ハフマン圧縮のみ。(RLE無し)

  • 3: RLE のマッチ距離を1にする

  • 4: 固定ハフマン圧縮


png:swap-bytes

ImageMagick-6.8.8-3 からの機能です。

PNG は bit-depth=16 の時にネットワークバイトオーダー、つまりビッグエンディアンで値を格納します。

ここに(多分間違えて)リトルエンディアンで入れてくる機械があるそうで、その対処用みたいです。


png:exclude-chunk

特定のチャンクを取り除く事ができます。

例えば、コメントは tEXt チャンクに入るので、

% convert -comment "This is a rose." rose: rose-comment.png

% identify -verbose rose-comment.png | grep -i comment
Image: rose-comment.png
comment: This is a rose.

ここから tEXt を消してみます。

% convert rose-comment.png -define png:exclude-chunk=tEXt out.png

% identify -verbose out.png | grep -i comment
comment: This is a rose.

ぐぬぬ。。そういえば zlib 圧縮してコメントを格納する zTXt チャンクがありますね。。

% convert rose-comment.png -define png:exclude-chunk="tEXt,zEXt" out.png

% identify -verbose out.png | grep -i comment
%

めでたく消えました。


png:include-chunk

png:exclude-chunk の逆のようです。


その他

チャンクの種類ごとにいろんな指定がありますが、数が多すぎますし疲れたので、また今度気が向いたら。

これって何?といった質問があれば追記します。


参考


おわり

以上です。