ImageMagick
WebP

ImageMagick と WebP

ImageMagick の WebP 対応です。

WebP って?

Google が出してきた比較的最近の画像フォーマットです。VP8 動画コーデックの静止画圧縮を使います。

JPEG と似て、見た目気にならない程度に画像データを変化させてファイル容量を圧縮する方式です。JPEG よりさらにファイルサイズを削減できます。透明度も扱えます。

あと、WebP は GIF みたいなアニメーションを表現できますが、ImageMagick は未対応です。(最近も issue にあがったけどスルー気味)

使用上の注意として、WebP は YUV420 (色差成分が荒い)のみ対応なので、イラストや CG 画像を WebP ファイルとして保存すると画質の劣化が辛い事があります。特に偽色問題が有名です。あと、ブラウザによっては表示できないかも?

ImageMagick で WebP を使う

使えるか確認

WebP に対応しているか -list format コマンドで確認してください。(Linux 系の標準パッケージはまだのような?)

% convert -list format | grep WebP
     WEBP* WEBP      rw-   WebP Image Format (libwebp 0.6.1 [0208])
% convert rose: rose.webp
% identify rose.webp
rose.webp WEBP 70x46 70x46+0+0 8-bit sRGB 906B 0.000u 0:00.000

(蛇足ですが rw- のところ。アニメーション対応すると rw+ になります)

ダメなら libwebp のある環境で ImageMagick を自分でビルドしましょう。

自前でビルド

libwebp と ImageMagick の最新版をとってきます。

% tar xvfz libwebp-0.6.1.tar.gz
% cd libwebp-0.6.1
% ./configure --prefix=$HOME/libwebp/0.6.1
% make install
<略>
% tar xvfz ImageMagick-6.9.9-28.tar.gz
% cd ImageMagick-6.9.9-28
% ./configure --prefix=$HOME/ImageMagick/6.9.9-28 --with-webp=yes --with-webp-dir=$HOME/libwebp/0.6.1
% make install
<略>
% $HOME/ImageMagick/6.9.9-28/bin/convert -list format | grep WebP
     WEBP* rw-   WebP Image Format (libwebp 0.6.1[0208])

JPEG と雑に比較する

本来はたくさんの画像で検証すべきですが、ちょっと雑に実験。

% convert fujisan-800.png fujisan-800.jpg
% convert fujisan-800.png fujisan-800.webp
% ls -l fujisan-800.png fujisan-800.jpg fujisan-800.webp
-rw-r--r--  1 yoya  staff  133519 12 26 16:42 fujisan-800.jpg
-rw-r--r--@ 1 yoya  staff  631243 12 26 16:41 fujisan-800.png
-rw-r--r--  1 yoya  staff   43302 12 26 16:42 fujisan-800.webp

わぉ。。。と喜びたい所ですが、実はデフォルトで出力する画質が違います。
実際に並べて見ると、細部が微妙に潰れて見えると思います。 (Qiita は WebP を貼れないので、PNG として貼ります)

fujisan-800.jpg.png
fujisan-800.jpg.png
fujisan-800.webp.png
fujisan-800.webp.png

compare コマンドで SSIM 算出してみます。

% compare -verbose -metric ssim  fujisan-800.png fujisan-800.jpg null:
fujisan-800.png PNG 800x534 800x534+0+0 8-bit sRGB 631243B 0.020u 0:00.019
fujisan-800.jpg JPEG 800x534 800x534+0+0 8-bit sRGB 133519B 0.020u 0:00.019
Image: fujisan-800.png
  Channel distortion: SSIM
    red: 0.976227
    green: 0.980428
    blue: 0.969786
    all: 0.97548
fujisan-800.png=> PNG 800x534 800x534+0+0 8-bit sRGB 1.190u 0:01.210
% compare -verbose -metric ssim  fujisan-800.png fujisan-800.webp null:
fujisan-800.png PNG 800x534 800x534+0+0 8-bit sRGB 631243B 0.020u 0:00.019
fujisan-800.webp WEBP 800x534 800x534+0+0 8-bit sRGB 43302B 0.020u 0:00.019
Image: fujisan-800.png
  Channel distortion: SSIM
    red: 0.936094
    green: 0.945314
    blue: 0.923273
    all: 0.934894
fujisan-800.png=> PNG 800x534 800x534+0+0 8-bit sRGB 1.400u 0:01.639

ちょっとこれは不公平な感じです。

JPEG quality に合わせる。

% identify -verbose fujisan-800.jpg | grep Qual
  Quality: 92
% convert -define webp:emulate-jpeg-size=true -quality 92 fujisan-800.png  fujisan-800-q92-jpegemu.webp
fujisan-800-q92-jpegemu.webp.png
fujisan-800-q92-jpegemu.webp.png

SSIM もいい感じの値です。

% compare -verbose -metric ssim  fujisan-800.png fujisan-800-q92-jpegemu.webp null:
fujisan-800.png PNG 800x534 800x534+0+0 8-bit sRGB 631243B 0.010u 0:00.019
fujisan-800-q92-jpegemu.webp WEBP 800x534 800x534+0+0 8-bit sRGB 113914B 0.030u 0:00.009
Image: fujisan-800.png
  Channel distortion: SSIM
    red: 0.984659
    green: 0.991055
    blue: 0.977479
    all: 0.984398
fujisan-800.png=> PNG 800x534 800x534+0+0 8-bit sRGB 1.410u 0:01.670
% ls -l fujisan-800.jpg  fujisan-800-q92-jpegemu.webp
-rw-r--r--  1 yoya  staff  113914 12 26 17:04 fujisan-800-q92-jpegemu.webp
-rw-r--r--  1 yoya  staff  133519 12 26 16:42 fujisan-800.jpg

劇的には減っていませんが、そこそこ節約できています。
SSIM の値を見ると今度は JPEG より品質が良すぎるので、もっと quality 下げないと逆に不公平ですし、のっぺりするのを問題にするのであれば filter-sharpness で対処もできます。まだまだファイルサイズを減らす余地があると言えます。

-define webp:〜

ここからは具体的なパラメータの解説です。
実質 libwebp や VP8 の説明になっています。
ImageMagick の webp モジュールはほぼ libweb を呼ぶだけで、webp:〜 オプションで指定した値は、そのまま libwebp の WebPConfig に渡ります。そこから更に VP8 に横流しされたりします。

webp:lossless (boolean)

true で画像を劣化させない圧縮です。処理に時間がかかる上に劣化を伴う圧縮ほどはファイスサイズが減りません。

% convert fujisan.png fujisan.webp
% convert fujisan.png -define webp:lossless=true fujisan-lossless.webp
% ls -l fujisan.png fujisan.webp fujisan-lossless.webp
-rw-r--r--  1 yoya  staff   7537942 12 26 17:39 fujisan-lossless.webp
-rw-r--r--@ 1 yoya  staff  11179570 12 12 01:31 fujisan.png
-rw-r--r--  1 yoya  staff    702622 12 26 17:39 fujisan.webp

webp:method (integer)

圧縮メソッドで 0〜6の値でデフォルトは 4 。
エンコード速度、圧縮サイズ、画質のトレードオフを制御できます。
値を増やすほど圧縮に時間をかけて頑張ります。値を減らすと速い代わりに画質も圧縮も低下していきます。

% for m in `seq 0 1 6` ;
    do convert fujisan.png -define webp:method=$m fujisan-method-$m.webp ;
  done
% ls -l fujisan-method-?.webp
-rw-r--r--  1 yoya  staff   1216252 12 26 17:45 fujisan-method-0.webp
-rw-r--r--  1 yoya  staff    883528 12 26 17:45 fujisan-method-1.webp
-rw-r--r--  1 yoya  staff    760004 12 26 17:45 fujisan-method-2.webp
-rw-r--r--  1 yoya  staff    700532 12 26 17:45 fujisan-method-3.webp
-rw-r--r--  1 yoya  staff    702622 12 26 17:45 fujisan-method-4.webp
-rw-r--r--  1 yoya  staff    667396 12 26 17:45 fujisan-method-5.webp
-rw-r--r--  1 yoya  staff    648458 12 26 17:45 fujisan-method-6.webp

webp:image-hint (string)

default, photo, picture, graph の4種類を選べます。
指定したシーンに適したエンコードをしてくれるはずです。

webp:target-size (int)

目標とする画像サイズを指定できます。単位はバイト数。(KやMではない。ビットでもない)
あと、これはあくまで目標値です。

webp:target-psnr (double)

目標とする画質を指定できます。こちらもあくまで目標値です。
PSNR なので dB 単位。 42 がよく使われます。

webp:segments (int)

セグメントの個数です。1〜4が指定できて デフォルトが4です。

webp:sns-strength (int)

どの画像領域でビット数がより減った方が良いのかを探すアルゴリズム(spatial noise shaping)で、0 は無し。100は最大限に努力します。
デフォルトは50です。

webp:filter-strength (int)

ブロッキングフィルタの強さです。0がオフ、100が最大です。大きいほど滑らかになります。20〜50 がよく使われます。

webp:filter-sharpness (int)

ぼやけを抑えるよう、画像をシャープ(先鋭化)にするフィルタをかけます。

webp:filter-type (int)

0:nostrong(off (-nostrong相当)、1:simple (-strong相当) 2: complex
例えば、simpleだとマクロブロックの外2pixelのluma(chromaはフィルタしない)をフィルタしますが、complex は3pixelまでフィルタにかけます。(frame_dec.c)

webp:auto-filter (boolean)

true にすると品質的にバランスのよい最適化を行います。

webp:alpha-compression (int)

透明度データを圧縮するなら 1、しないなら 0。確かロスレスのはず。

webp:alpha-filtering (int)

透明度データのフィルタ指定。 0:なし、1:fast(default)、2:best

webp:alpha-quality (int)

透明度データの画質を指定します。量子化レベルを指定します。

  • Quality:[0, 70] -> Levels:[2, 16]
  • Quality:]70, 100] -> Levels:]16, 256].

70を境に量子化のレベルの扱いが切り替わります。

webp:pass (int)

-psnr or -size で指定した目標値に近くためのパスの最大回数です。

webp:show-compressed (int)

圧縮した画像をユーザメモリを返す機能だけど、よくわかりません。^^;

webp:preprocessing (int)

0=none, 1=segment-smooth, 2=pseudo-random dithering.
ソースではフラグ処理をしてるので、マニュアルにはないが、3 だと 1 と 2 の両方できるかも。

webp:partitions (int)

progressive decoding: 0〜3 から選択。

webp:partition-limit (int)

1つ目のパーテーションを 512K に合わて画質を下げるかどうか。0 は何もしない。100 は全力。

webp:emulate-jpeg-size (boolean)

quality 指定を JPEG 相当に似せる。
JPEG では quality75 がバランス良いが、内部的には 50 なので、そのマッピングを行う。

webp:low-memory (boolean)

true にするとメモリ使用を抑えます。ただしエンコードは遅くなります。

webp:thread-level (int)

マルチスレッドエンコード。0:無効、1(以上): 有効。

参考 URL