4.1K Views
March 13, 24
スライド概要
ImageMagick で WebP を扱う処理の詳細。
ImageMagick 内部入門 第十四回 (WebP) 2024/03/15(金) “よや” <[email protected]>
内部入門シリーズ • (第一回) 全体構成 • (第二回) データ構造 〜 ImageList, ImageInfo • (第三回) Magick API 〜 MagickWand / MagickCore • (第四回) 画像形式処理 〜 Coders と Delegate • (第五回) メタデータ 〜 xmp, profile • (第六回) システム設定 〜 policy.xml 等 • (第七回) 減色 • (第八回) ビットdepth 〜 depth 変換 • (第九回) 2値化 〜 threshold • (第十回) ディザリング 〜 組織 (拡散ディザは延期) • (第十一回) ICCプロファイル 〜 RGB CMYK 色空間 • (第十二回) 色フィルタ 〜 Colorize ColorMatrix • (第十三回) 色modulate 〜 modulate (変調) • (第十四回) WebP ← ☜ 今回の話 • (第十五回) Displace 〜 Displace map • (第十六回) 分散処理 〜 OpenMP, distribute-pixel-cache • (第N回) 各画像処理 (畳み込み、モルフォロジー) 〜 ColorCube
目次 • WebP 仕様 (概要) • • • • • WebP とは WebP Lossy – VP8 WebP Lossless WebP Alpha (透明度) WebP Animation • ImageMagick の WebP (具体的な話) • • • • • • • • Lossy Lossless Alpha Quality Animation Sharp YUV webp:〜 設定 preset (libweb-cwebp 機能)
WebP (ウェッピー)とは • 2010年に Google が発表した画像フォーマット • 2022年に対応ブラウザが揃う(Safari が最後) • Web 表示に於ける JPEG, PNG, GIF の代替候補 • Lossy 形式は JPEG の代替 • VP8 Intra フレームを利用 (H.26x 系だとライセンスが障害になる) • Lossless は PNG の代替 • パレット形式も対応 > PNG8, GIF • Alpha plane (透明度)も扱える > PNG32, GIF • アニメーションは GIFアニメーション、APNG の代替 • 256色に限定しない。フルカラーアニメーション
WebP Lossy – VP8 • 話題になる WebP は多くの場合 Lossy • JPEG でお馴染みの不可逆(劣化あり)圧縮 % magick input.jpg output.webp % identify -format "%m quality:%[quality]\n" output.webp WEBP quality:0 • VP8 動画の一コマを RIFF で包んだ画像形式 • 昔、Flash で使われた On2 VP6 の後継。AOM-AV1 の先祖のひとつ • JPEG より圧縮効率が良い? • Mozilla は JPEG がもっと頑張れば WebP は必要ないと主張 • JPEG は噛めば噛むほど味がする。Guetzli や最近だと jpegli (libjxl 付属) • Chrome Subsampling 4:2:0 のみ対応なのが欠点。VP8 の制限
WebP Lossless • PNG や TIFF でお馴染みの Lossless 。可逆圧縮 • Near-lossless と呼ぶ劣化つき圧縮機能もある。(libwebp の機能) % magick input.png -define webp:lossless=1 output.webp # –quality 100 でも可 % identify -format "%m quality:%[quality]\n" output.webp WEBP quality:100 • 技術要素としては PNG の改良版に近い。LZ + ハフマン • パレット形式も対応。 • 8bit 限定なのが弱点。(恐らく Web 表示用として割り切り)
WebP Alpha • 透明度(Alpha plane) も対応 • GIF や PNG32 でお馴染みの透明度 • Alpha plane は可逆圧縮 (lossless) • WebP Lossless と同じ形式。 • libwebp に near-lossless 風の実装がある % magick input.png PNG32.webp # alpha 有り % identify -format "%m %[channels] alpha:%A\n" PNG32.webp WEBP srgba 4.0 alpha:Blend RGB plane Alpha plane
WebP Animation • アニメーションも可能 • Lossy, Lossless 両対応 % magick input.gif output.webp # アニメーション % identify output.webp output.webp[0] WEBP 328x144 328x144+0+0 8-bit sRGB 19588B 0.000u 0:00.000 output.webp[1] WEBP 120x40 328x144+32+56 8-bit sRGB 0.000u 0:00.000 output.webp[2] WEBP 112x56 328x144+24+48 8-bit sRGB 0.000u 0:00.000 output.webp[3] WEBP 64x56 328x144+48+48 8-bit sRGB 0.000u 0:00.000 output.webp[4] WEBP 328x144 328x144+0+0 8-bit sRGB 0.000u 0:00.000 output.webp[5] WEBP 40x24 328x144+40+64 8-bit sRGB 0.000u 0:00.000 output.webp[6] WEBP 120x24 328x144+32+64 8-bit sRGB 0.000u 0:00.000 output.webp[7] WEBP 128x40 328x144+24+56 8-bit sRGB 0.000u 0:00.000
ImageMagick と WebP • ImageMagick は 6.6.8(2011年3月) にて対応 • 当初不具合が多くて実用的なのは 6.8.6-8(2013年7月)以降 • アニメーション対応は 7.0.8-68(2019年10月) • Blend モード対応は 7.0.10-26(2020年8月) • webm/libwebp を利用 • https://chromium.googlesource.com/webm/libwebp • 実装は ImageMagick/coders/webp.c • https://github.com/ImageMagick/ImageMagick/tree/main/coders/webp.c • -define webp:〜=〜 で色々制御できる。ほぼ libwebp にそのままパラ メータが渡る
WebP Lossy • デフォルトで Lossy に変換される • JPEG だけでなく PNG や GIF が元でもデフォルト Lossy 変換。 • identify 表示の quality は 0 % magick input.jpg JPEG.webp % magick input.png PNG.webp % magick input.gif GIF.webp % identify -format "%m quality:%[quality]\n" JPEG.webp WEBP quality:0 % identify -format "%m quality:%[quality]\n" PNG.webp WEBP quality:0 % identify -format "%m quality:%[quality]\n" GIF.webp WEBP quality:0
WebP Lossless • -define webp:lossless=1 で Lossless変換 • ちなみに、-quality 100 でも lossless 変換になる。 • identify 表示の quality は 100 % magick input.jpg –define webp:lossless=1 JPEG.webp % magick input.png –define webp:lossless=1 PNG.webp % magick input.gif –define webp:lossless=1 GIF.webp % identify -format "%m quality:%[quality]\n" JPEG.webp WEBP quality:100 % identify -format "%m quality:%[quality]\n" PNG.webp WEBP quality:100 % identify -format "%m quality:%[quality]\n" GIF.webp WEBP quality:100
WebP lossless (8bit制限) • WebP Lossless は bit depth が 8bit 限定なのに注意。 • TIFF や PNG は 16bit 画像が意外と多く、これらを 8bit に変換 すると精度が落ちて元画像と差分が出る。つまり劣化する。 • ImageMagick 自体がカジュアルに TIFF や PNG で 16bit 画像 を出力するので、厄介。 % magick -version Version: ImageMagick 7.1.1-27 Q16-HDRI aarch64 21931 (略) % magick -size 100x100 gradient:blue-red blue-red.png % identify blue-red.png blue-red.png PNG 100x100 100x100+0+0 16-bit sRGB 916B 0.000u 0:00.000
WebP Alpha • 画像データの透明度は WebP に保存される。 • %A で Blend 表示。なお、Lossless 圧縮。 % magick input.png PNG32.webp # alpha 有り % identify -format "%m %[channels] alpha:%A\n" PNG32.webp WEBP srgba 4.0 alpha:Blend % magick input.jpg -alpha activate JPEG-Alpha.webp % identify -format "%m %[channels] alpha:%A\n" JPEG-Alpha.webp WEBP srgba 4.0 alpha:Blend • 透明度を含まない時は、%A で Undefined 表示 % magick input.jpg JPEG.webp # alpha 無し % identify -format "%m %[channels] alpha:%A\n" JPEG.webp WEBP srgb 3.0 alpha:Undefined
WebP alpha (コンテナ構造) • Lossy と Lossless で Alpha plane の持ち方が異なる • Lossy は Alpha が別チャンク。Lossless は RGBA まとめて格納 Lossy (Alpha無し) RIFF VP8 WEBP Lossy (Alpha有り) RIFF WEBP VP8X Lossless (Alpha有無どっちも) RIFF WEBP VP8L YUV ALPH VP8 A YUV RGBA
WebP quality • –quality で画質の劣化具合を調整できる • quality の値と劣化具合の傾向は JPEG と異なる % magick Fujisan.png –quality 10 fujisan.jpg • バンディングが生じている • JPEG は一目で劣化が分かる % magick Fujisan.png –quality 10 fujisan.webp • 細部が潰れてのっぺりする (動画コーデックの特徴) • WebP は元と比較しないと劣化が分かり辛い
WebP quality (lossless) (1/2) • 可逆圧縮の lossless で劣化圧縮ができる (禅問答?) % magick input.png –define webp:lossless=1 –quality 50 output.jpg • -define webp:lossless=1 の状態で –quality 指定。 • なお。-quality 100 の時は自動で -define webp:lossless=1 扱い • near-lossless と呼ぶ libwebp の仕様外機能 • 周囲とコントラスト差のあるピクセルは量子化粒度を下げる
WebP quality (lossless) (2/2) • 量子化の仕組み そのまま 維持 キリの良い数値にする (少し位変えても見た目分からない) 輝度 レベル キリの良い数値にする 色が重複して色数が減る エントロピー(情報量)が下がる 色 • libwebp の該当コード エントロピー圧縮がよく効く webm/libwebp/src/enc/near_lossless_enc.c int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, uint32_t* const argb_dst) {
WebP quality (alpha) • -define webp:alpha-quality で指定できる。 % magick input.png –define webp:alpha-quality=50 output.jpg • Lossless の near-lossless と概念は同じで画像自体のエントロ ピーを減らして圧縮率を高める • ただ、near-lossless より高度な処理もしてる。 • k-means での減色処理とか。(重たそう) webm/libwebp/src/enc/alpha_enc.c static int EncodeAlpha(VP8Encoder* const enc, (略) => QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse);
WebP ファイルサイズ増加の罠 • WebP 変換でファイルサイズが増える罠 FAQ • YUV420 への変換で元にない色が発生してサイズが膨らむ • JPEG 等の Lossy を WebP Lossless に変換すると膨らむ • 元が JPEG で生成した時の Quality 値より大きな値で WebP を 作成。 • それ以外にも当然ありまして。。 (次ページで解説)
WebP ファイルサイズ増加の罠 (RGBA) • PNG32 を JPEG 変換すると透明度が落ちる一方 WebP は残る • しかも、WebP の透明度は可逆圧縮(lossless)。サイズ大きめ • 以下のファイルでサイズを比較してみる。(グラフは次ページ) RGBA % magick rose: -resize 240 \( +clone -fill white -colorize 100% \ -background black -vignette 32x32 \) -alpha off \ -compose copy_opacity -composite rose-vignette.png % for q in `seq 10 10 90` ; do magick rose-vignette.png -alpha off \ -define webp:emulate-jpeg-size=1 -quality $q \ WebP-RGB-$q.webp ; done RGB A
WebP ファイルサイズ増加の罠 • WebP だけ透明度が残るので RGB の圧縮が良くても A の分 WebP が太って見える JPEG YUV PNG32 VP8L Lossy WEBP VP8X RGBA ALPH VP8 A Lossless YUV Lossy
WebP ファイルサイズ増加の罠 (比較図) • 変換元が PNG32 だと WebP はデフォルトで 透明度を含むので、 JPEG より膨らむ。 => WebP-RGBA Filesize(bytes) WebP-RGBA • -alpha off 等で透明度 を削除して比較すると 良さそう。 => JPEG と WebP-RGB • 図でいう青と赤の線を 比較するべき JPEG この差はalpha分 WebP-RGB Quality
WebP ファイルサイズ増加の罠 (比較図2) • 透明度はマスク的に使う事が多いので、右の方がより適切 Filesize(bytes) Filesize(bytes) JPEG WebP-RGBA JPEG この差はalpha分 WebP-RGBA この差はalpha分 WebP-RGB Quality WebP-RGB Quality
WebP Animation • アニメーションも可能 • Lossy, Lossless 両対応 差分フレーム なので大きさバラバラ % magick input.gif output.webp # アニメーション % identify output.webp output.webp[0] WEBP 328x144 328x144+0+0 8-bit sRGB 19588B 0.000u 0:00.000 output.webp[1] WEBP 120x40 328x144+32+56 8-bit sRGB 0.000u 0:00.000 output.webp[2] WEBP 112x56 328x144+24+48 8-bit sRGB 0.000u 0:00.000 output.webp[3] WEBP 64x56 328x144+48+48 8-bit sRGB 0.000u 0:00.000 output.webp[4] WEBP 328x144 328x144+0+0 8-bit sRGB 0.000u 0:00.000 output.webp[5] WEBP 40x24 328x144+40+64 8-bit sRGB 0.000u 0:00.000 output.webp[6] WEBP 120x24 328x144+32+64 8-bit sRGB 0.000u 0:00.000 output.webp[7] WEBP 128x40 328x144+24+56 8-bit sRGB 0.000u 0:00.000
Sharp YUV (1/3) • Chroma Subsampling • RGB を 輝度Y,色差UV(CbCr)に変換して保持する方式。JPEGもこれ • 色差の UV を間引く事ができる。 • このうち WebP (lossy) – VP8 は YUV420 のみ対応
Sharp YUV (2/3) • YUV420 で素朴な処理だと色劣化する。 JPEG でも発生する 4:4:4 => 4:2:0
Sharp YUV (3/3) • 色味をなるべく維持する処理 > sharp-yuv • webp:use-sharp-yuv で指示する。 % magick grid.png webp:use-sharp-yuv=1 output.webp • デメリット • サイズが1〜2割増える。エンコード処理時間も2割ほど増える。 % ls -l rb-grid.webp rb-grid-sharp-yuv.webp -rw-r--r-- 1 yoya staff 3118 2 19 19:40 rb-grid-sharp-yuv.webp -rw-r--r-- 1 yoya staff 2770 2 19 19:39 rb-grid.webp • (JPEGエンコーダにも欲しい機能) output.webp
webp:〜 設定 • -define webp:〜 での指示は多岐に渡る。 • よく使いそうなオプション。 • • • • • webp:emulate-jpeg-size webp:lossless webp:use-sharp-yuv webp:filter-sharpness webp:image-hint -quality の画質を JPEG に近づける lossless/lossy の切り替え 色劣化の問題改善 ボケの軽減 シーンに応じた設定プリセット • 以下のサイトで一通りの webp:〜 を紹介してます • https://qiita.com/yoya/items/0848a6b0b39db4cd57c2#-definewebp
ImageMagick の WebP 実装 • libwebp の API で普通にデコード
ImageMagick の Webp 実装 • -define webp:〜 で libwebp に色々指示
preset (libwebp の機能) • libweb-cwebp はシーン別設定例をプリセット指定できる sns sharpness non-block dither segments (default) 50 0 60 no 4 picture 80 4 35 no - photo 80 3 30 yes - drawing 25 6 10 - - icon 0 - 0 no - text 0 - 0 no 2 • sns (spatial noise shaping): どの領域でビットを減らすか探索 • segments: マクロブロック毎に切り替える設定バンク数
preset (ImageMagick を使う場合) • ImageMagick は preset を libwebp に渡す仕組みがない • 先程の表を参考に各種パラメータを設定しましょう • • • • • sns: webp: -define webp:sns-strength=(int) sharpness: -define webp:filter-sharpness=(int) non-block: -define webp:filter-strength=(int) dither: -define webp:preprocessing=(int) dither on は 2 segments: -define webp:segments=(int) • preset : picture 相当のオプション例 % magick input.png –define webp:sns-strength=80 –define webp:filter-sharpness=4 ¥ -define webp:filter-strength=35 –define webp:preprocessing=0 output.webp
参考サイト • 公式 • • • • • https://developers.google.com/speed/webp?hl=ja https://developers.google.com/speed/webp/faq?hl=ja https://chromium.googlesource.com/webm/libwebp https://imagemagick.org/script/webp.php ImageMagick https://chromium.googlesource.com/webm/libwebp • WebP 解説 • https://qiita.com/yoya/items/0848a6b0b39db4cd57c2 ImageMagick • https://qiita.com/yoya/items/a000c2e123d448a37f47 Lossless • https://qiita.com/yoya/items/f5ef9b66b556eda9e6bf 色劣化の改善 • Chroma Subsampling • https://blog.awm.jp/2016/02/10/yuv/
おわり • 以上です