LoginSignup
1
1

More than 1 year has passed since last update.

ImageMagick のガンマ補正

Last updated at Posted at 2021-08-20

はじめに

ImageMagick のガンマ補正解説です。なお、PNG 出力結果は非直感的で個人的に不具合だと思いますが、それを含めて現状を説明します。

ImageMagick のガンマ補正

ImageMagick のガンマ補正オプションには、-gamma, +gamma があります。あと実は -level もそうです。

Gamma adjusts the image's channel values pixel-by-pixel according to a power law, namely, pow(pixel,1/gamma) or pixel^(1/gamma), where pixel is the normalized or 0 to 1 color value. For example, using a value of gamma=2 is the same as taking the square root of the image.

つまり、指定した値の逆数で輝度0〜1(max)の値をべき乗計算します。

image.png
(c) https://ja.wikipedia.org/wiki/ガンマ値

-level は本来レベル補正(線形コントラスト補正)ですが、同時にガンマ補正も行えます。

-level black_point{,white_point}{%}{,gamma}
(略)
Gamma will do a -gamma adjustment of the values. If it is omitted, the default of 1.0 (no gamma correction) is assumed.

これらのうち、-gamma は出力先が JPEG や TIFF の際には直感的に使えますが、PNG では恐らく意図しない結果になるでしょう。
PNG の場合は画像のRGBデータと一緒にメタデータのガンマ値(gAMAチャンク)まで弄る為です。

PNG gAMA チャンクについては以下の記事を参考にどうぞ。

サンプル画像

以下のコマンドで生成した画像をサンプルとして用います。グレースケールとカラー画像の2つです。

% convert -size 200x100 xc:white -fx "floor(i/w*5)/4*u" -depth 8 white.png
% convert -size 200x100 xc:cyan  -fx "floor(i/w*5)/4*u" png24:cyan.png
white.png cyan.png
white.png cyan.png

-gamma

このオプションは低輝度と高輝度をなるべくそのままに、中輝度の明るさを調整したい。といった事に便利です。

こちらだとブラウザで試せるので、単純なガンマ補正を体感したい方はどうぞ。

JPEG の挙動

まず、JPEG 出力で試してみます。

% convert white.png -gamma 2.0 white-2.0.jpg
% convert cyan.png  -gamma 2.0 cyan-2.0.jpg
white-2.0.jpg cyan-2.0.jpg
white-2.0.jpg cyan-2.0.jpg

この画像は確かに $ pixel^{1.0/2.0} $ の明るさに変化しています。
これが本来意図した -gamma の挙動でしょう。

PNG の挙動

PNG 出力だと、結果が明るすぎます。(ただし、画像ビューアによっては JPEG と同じ明るさに見える事もある)

JPEG 出力だと -gamma 2.0 を二回適用したのと同等です。

% convert white.png -gamma 2.0 white-2.0.png
% convert cyan.png  -gamma 2.0 cyan-2.0.png
% convert white.png -gamma 2.0 -gamma 2.0 white-2.0-2.0.jpg
% convert cyan.png  -gamma 2.0 -gamma 2.0 cyan-2.0-2.0.jpg
white-2.0.png cyan-2.0.png
white-2.0.png cyan-2.0.png
white-2.0.jpg cyan-2.0.jpg
white-2.0.jpg cyan-2.0.jpg
white-2.0-2.0.jpg cyan-2.0-2.0.jpg
white-2.0-2.0.jpg cyan-2.0-2.0.jpg

先ほど言及したように、PNG のメタデータのガンマ値が変化しているのが原因です。

% identify -verbose cyan.png | grep gamma
    png:gAMA: gamma=0.45455 (See Gamma, above)
% identify -verbose cyan-2.0.png | grep gamma
    png:gAMA: gamma=0.9091 (See Gamma, above)

0.45455=(1.0/2.2) から 0.9091=(1.0/(2.2/2.0) = 1.0/1.1) に変化しています。
まともな画像ビューアはこの gAMA 値で補正して表示する為、余計に色が明るくなるのです。(たまに無視するのもいます)

これ自体は、+gamma で対処可能です。
とはいえ、この挙動には自分も納得いっていませんし、ワークアラウンド扱いです。
あと、-level はガンマ補正もできて、かつ gAMA を弄らないので、こちらを使う方が良いかもしれません。

+gamma

+gamma は画像データはそのままで、メタデータのガンマ値だけ上書きするオプションです。なお、0.45455 は 1.0/2.2 相当です。

% convert white-2.0.png +gamma 0.45455 white-2.0+0.45455.png
% convert cyan-2.0.png  +gamma 0.45455 cyan-2.0+0.45455.png

これでガンマ値が元に戻るので、JPEG と同様の表示になる PNG 画像が作れます。

white-2.0+0.45455.png cyan-2.0+0.45455.png
white-2.0+0.45455.png cyan-2.0+0.45455.png
white-2.0.jpg cyan-2.0.jpg
white-2.0.jpg cyan-2.0.jpg
% identify -verbose cyan-2.0+0.45455.png | grep gamma
    png:gAMA: gamma=0.45455 (See Gamma, above)

なお、JPEG や GIF はメタデータとしてガンマ値を置けないので、+gamma を使っても表示が変わりません。

-level

% convert white.png -level "0,100%,2.0" white-levelgamma-2.0.png
% convert cyan.png -level "0,100%,2.0" cyan-levelgamma-2.0.png

こっちは見た目も JPEG と同じです。

white-levelgamma-2.0.png cyan-levelgamma-2.0.png
white-levelgamma-2.0.png cyan-levelgamma-2.0.png
white-2.0.jpg cyan-2.0.jpg
white-2.0.jpg cyan-2.0.jpg

-gamma と違って gAMA が不変で、RGB データだけ変換するので直感的に使えます。

% identify -verbose cyan-levelgamma-2.0.png | grep gamma
  Filename: cyan-levelgamma-2.0.png
    png:gAMA: gamma=0.45455 (See Gamma, above)

PNG 生成

ついでに -gamma/+gamma 関係なく、PNG 生成する時に gAMA がどう扱われるかの、簡単なまとめです。

新規 PNG 生成

ImageMagick で PNG ファイルを一から生成すると 0.45455(=1.0/2.2) の gAMA チャンクが付与されます。

% convert -size 200x100 xc:white -depth 8 -fx "floor(i/w*5)/4*u" white.png
% convert -size 200x100 xc:cyan  -fx "floor(i/w*5)/4*u" png24:cyan.png

PNG から変換

画像ファイルを渡して PNG ファイルに変換する場合は、元のガンマ値を引継ぎます。

% identify -verbose cyan-2.0.png | grep gamma
    png:gAMA: gamma=0.9091 (See Gamma, above)
% convert cyan-2.0.png -resize 50% cyan-2.0-x50%.png
% identify -verbose cyan-2.0-x50%.png | grep gamma
    png:gAMA: gamma=0.9091 (See Gamma, above)

JPEG から変換

JPEG のメタデータにはガンマ値を含められないので、2.2 相当(実際には 1.0/2.2)のガンマ値として PNG 生成されます。

% convert cyan-2.0.png   cyan-2.0.png.jpg  # メタデータのガンマ値が消える
% convert white-2.0.png  white-2.0.png.jpg # 〃〃
% convert white-2.0.png.jpg white-2.0.png.jpg.png  # ガンマ値がないので、0.45455 が埋まる
% convert cyan-2.0.png.jpg cyan-2.0.png.jpg.png    # 〃〃
% identify  -verbose white-2.0.png.jpg.png  | grep gamma
    png:gAMA: gamma=0.45455 (See Gamma, above)
% identify  -verbose cyan-2.0.png.jpg.png  | grep gamma
    png:gAMA: gamma=0.45455 (See Gamma, above)
1
1
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
1
1