0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pngquantでpng容量削減圧縮したときなぜかグレースケール化したpngの方が容量が大きくなってしまう問題

Last updated at Posted at 2020-12-17

TL;DR (Too Long, Didn’t Read) 要約

pngquantは画像がグレースケールと見るや仕事をサボる1ので、--quality -90 オプションで働かせましょう。

えっ!?グレースケール画像の方が容量でかくね?

自炊したページをpngquantにかけて容量削減しようとしたとき、ふと気が付くと白黒2色刷りページの、グレースケール化したpngより、グレースケール化していないpngの方がpngquantにかけた後の容量が小さくなってるのに気づきました。

対象 pngquant処理前 pngquant処理後
グレースケール化していないpng 961.6KB 270.9KB
グレースケール化したpng 321.8KB 296.5KB

容量を少しでも減らしたいがためにグレースケール化してるのにしていない方が容量が小さいなんてこれは許容できません。
なんでこんな逆転現象が生じてるのか、グレースケール化した方をしてないものより容量を小さくするにはどうすればいいのか、調べました。

--verbose オプションで何が起こってるのか調べる

グレースケール処理していない画像をpngquantした結果

96652色の色が使われていることを検出。
(Q=89) 品質89で処理されたことがわかりました。(961.6KB→270.9KB)

$ pngquant --verbose --ext _new.png --speed 1 256 nonGS.png
nonGS.png:
  read 962KB file
  made histogram...96652 colors found
  selecting colors...4%
  selecting colors...9%
  selecting colors...14%
  selecting colors...42%
  selecting colors...47%
  selecting colors...52%
  selecting colors...80%
  selecting colors...100%
  moving colormap towards local minimum
  eliminated opaque tRNS-chunk entries...0 entries transparent
  mapped image to new colors...MSE=3.154 (Q=89)
  writing 256-color image as nonGS_new.png
  copied 1KB of additional PNG metadata
Quantized 1 image.

一方、グレースケールされた画像をpngquantした結果

256色の色が使われていることを検出。
(Q=100) 品質100で処理されたことがわかりました。(321.8KB→296.5KB)
そしてカラー画像のときのような処理をしていないように見受けられます。

$ pngquant --verbose --ext _new.png --speed 1 256 GS.png
GS.png:
  read 322KB file
  made histogram...256 colors found
  eliminated opaque tRNS-chunk entries...0 entries transparent
  mapped image to new colors...MSE=0.000 (Q=100)
  writing 256-color image as GS_new.png
  copied 1KB of additional PNG metadata
Quantized 1 image.

つまりpngquantはカラー画像を読ませるとゴリゴリに処理するのに対して、グレースケール画像を読ませると圧縮の必要なしと見なしてほとんど処理してくれないのです。

これを解消するには、グレースケール画像であろうとpngquantに強制的にカラー画像を読ませたときと同程度の削減処理をさせればいいわけです。

--qualityオプションでどんな画像であろうと一定レベルの削減を行うようにする

--quality [<min>]-[<max>] (または -Q [<min>]-[<max>])で品質を指定してグレイスケールでも削減させるようにします。qualityは0~100で指定してデフォルトでは100です。

$ pngquant --quality 0-50
$ pngquant --quality 80-100

カラー画像を処理する場合、およそ(Q=90)で処理されているので、同レベルの削減処理をさせるために、qualityを90に指定しましょう。<min>を省略して -90 と指定すると 0-90 を指定したことになり、品質90を狙って処理するということになります(多少誤差は出る)。

$ pngquant --verbose --ext _new.png --speed 1 --quality -90 256 GS.png
GS.png:
  read 322KB file
  made histogram...256 colors found
  selecting colors...2%
  selecting colors...4%
  selecting colors...6%
  selecting colors...8%
  selecting colors...10%
  selecting colors...23%
  selecting colors...25%
  selecting colors...38%
  selecting colors...40%
  selecting colors...42%
  selecting colors...55%
  selecting colors...57%
  selecting colors...70%
  selecting colors...82%
  selecting colors...95%
  selecting colors...100%
  moving colormap towards local minimum
  eliminated opaque tRNS-chunk entries...0 entries transparent
  mapped image to new colors...MSE=2.618 (Q=91)
  writing 29-color image as GS_new.png
  copied 1KB of additional PNG metadata
Quantized 1 image.

見事、(Q=91) で処理され、(321.8KB→155.2KB)と、だいぶ削減されたファイルが生成されました。
品質91といっても見た目はそんなに変わらないし、私としてはせっかくグレイスケールにしたのにカラー画像の方が容量が小さいという状況に我慢できなかったので、小さいファイルを手に入れることができたのでひとまず安心です。


ちなみに、pngquantにかける前のグレースケール画像は tweakpng.exe2 で調べてみると、PNG Header の Color 欄は 0=grayscale になっているのに、処理後のColor欄は 3=paletted になっていて、もしかしてpngquantってグレースケール画像をカラー画像化してる!?これが容量が逆転する原因!??って思いましたが、カラー画像の場合は 2=RGB なので、これは関係なかったみたいです。

参考

  1. これが原因だと思っていますが、間違っていたら教えてください。

  2. 【レビュー】PNG画像を解析して詳細なフォーマット情報を取得・表示するツール「TweakPNG」 - 窓の杜

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?