Gamma correction

by syoyo

gamma06_400.png
(image from Wikipedia)

レンダラコンサル(のようなもの)を引き続き続けています.

いくつかいただいた質問などの中から今回は、数人の方から同時に話題に上がったガンマ補正について調べたので書いてみます.
自分でも今までガンマ補正には, 存在には気づきつつも考慮していなかったため、よい勉強となりました.

ガンマ補正の実制作現場における問題については、すでに masuo さんが取り上げられています [2].
非常に参考になりますので、こちらも参考にしてください.

問題

CRT や液晶などの表示デバイスは、その特性状、入力の色の強度に線形比例して応答して発光せず、色の強度に対して曲線状に応答します(上図の下側の曲線).
この曲線は、 gamma(γ, ガンマ) という値を用いて表現することができます.
入力の強度が I であったとき, 実際に発光される色 I’ は、

I’ = I^gamma

という関係があります. I は通常 0.0(真っ黒) – 1.0(真っ白. 最大輝度) の範囲で定義されるので、gamma が高いほど曲線は下側に向きます.

入力で 0.5 の値を与えても、ちょうど中間のグレーが表示はされず、それよりも小さな値(より暗い色)が見えることになります.
(人間の知覚反応が強度に対して線形に反応するかという考慮はここでは割愛)

たとえば gamma = 2.2 のケースですと、入力のグレー値 0.5 は、0.5^2.2 = 0.21 の色強度として表示されます. なんと, 表示させたいと思っている値の半分以下です! 0-255 の階調で考えると、127(グレー)が実は 54 で見えているということになります. ガンマ、おそるべし.

この gamma 値は、OS によっても異なり、Windows では標準ですと 2.2, Mac は 1.8 となっています.

gamma が大きいほうが応答曲線はより大きく曲がり、暗い部分はより暗くなります. Windows だと色が引き締まってみえたり、Mac だと白っぽくなって見えたりするのはガンマがその原因のひとつと言えます.

ちなみに、Mac は今は gamma = 1.8 ですが、時期 OS である SnowLeopard からは Windows と同じ gamma = 2.2 になります. これで Windows と Mac でガンマの違いで見え方が異なる、という問題は無くなりますね.

ガンマ補正

表示デバイスを介すると、入力の強度に応じて線形に出力の強度が応答しないという問題がありました. この問題を解決して、線形に応答させるようにするのがガンマ補正です.

やり方は至って簡単です、「歪むのが分かっているのなら、逆方向に歪んだ入力を与えればいいじゃない]

つまり線形の入力(上図の y=x の線)を一旦上図の上側の曲線に変換したものをディスプレイに入力すれば, 目的とする線形に比例する応答が実現できるわけです.この変換は gamma の逆数を入力の強度にかけてあげれば OK です.

とはいえ、ディスプレイデバイスもそんな単純ではなくなってきているようです.

[3] のようにディスプレイによっては必ずしもガンマ乗に比例して階調が変化しないものがあったり、ディスプレイ側でガンマ補正が調整できるロジックの入った表示デバイスも出てきています(この場合、ディスプレイに画素を送るまえにガンマ補正を行うと逆におかしな結果になる).

昔の CRT ディスプレイのころとは違い, ガンマ補正を取り巻く問題はより複雑になったと言えるかもしれません.

テクスチャペインターの視点

というわけで、テクスチャペインターが描いたテクスチャなどのコンテンツは, テクスチャペインターがディスプレイを介して見ながら生成したものであるのでガンマがすでに付いている素材になります.
これをレンダラ側で使う場合にも、やはり適切にガンマ補正を行いガンマの歪みを取り除く必要があります.

ただし、masuo さんが述べているように、色でない要素、バンプテクスチャやディスプレースメントテクスチャでは、ガンマ補正の必要がない機会もあります.

ディスプレイが発達して、gamma=1 を再現できるのなら、そのキャリブレーション環境でテクスチャを作ってもらうのも一案ですが、デザイナーとしては「色味が変わるからやだ、自分に適した環境でなきゃいやだ」という声が上がりそうです.

よって、各デザイナごとの製作環境におけるガンマ値を適切に記録しておき, キャリブレーションして線形データにテクスチャを変換するというのが現実的な解でしょうか.

しかしそもそも、元々の精度が十分でないのも問題では?

しかし、ガンマ補正に関するより大きな問題は、現状のコンテンツ作成環境では入力が 8bit という時点で、ガンマ補正などを正しく考慮して各種変換を行う場合には, これはもはや十分な精度ではないということではないでしょうか.

そのため、各種変換操作を施しても精度が十分保てるように、16bit HDRI などより精度の高い環境でオリジナルのデータを作成するのが理想です.
最近は OpenEXR に代表される 16bit 画像フォーマットや Photoshop 16bit 化, Cinepaint などにより, 16bit HDR のコンテンツ作成環境が整備されてきていますので、だんだんと入力側の精度の問題は解決されていくと思います.

そうなってくれば、あとは純粋にデバイス間のキャリブレーションの問題(ディスプレイのガンマや色温度などを正しく知り、適切な変換を適用する)に落ち着きそうです.

PC からモニタへ表示データを送るときも、今だったら 8bit ではなくて 16bit で送るようなパスがありそうです. OS の API で存在したりしないのかな.
あと、GPU 経由であれば 16bit half で表示データをテクスチャとして持っておいて、矩形にテクスチャマッピングさせて表示させるという手もありますね.

共通のまとめ

ガンマ補正を適切に考慮しておきましょう.
コンテンツにはガンマ補正のプロファイルを保持しておきましょう.
入力データ(オリジナル)が 8bit というのは精度が問題である. 16bit 等高精度なフォーマットで持っておくのが望ましい. そうすれば、オリジナルがどのガンマで作られたとしても、各種変換で精度をあまり落とさず目的のガンマ画像に復元できるだろう.

レンダラ野郎向けのまとめ

色計算はすべて線形で(gamma=1). テクスチャや HDR 環境マップは使う前に gamma=1 に変換する. よってテクスチャにはどの gamma で作られたかの gamma 値の情報があることが望ましい.

レンダリング結果表示時にガンマ補正を行う.
(ただしファイル保存の場合は 16bit HDR のリニア(gamma=1)が望ましい)

色に関係しないコンポーネント(デプス、バンプ)はそのままで.

未解決の問題

さて、ガンマ補正、どうすればいいか解決したように見えて実はまだ問題がありそうです.

– アルファチャンネルはガンマ補正すべきか?(アルファがテクスチャペインターによって描かれた場合)
– また、アルファがある場合、カラーチャンネルのガンマ補正はいつ行うか?(アルファ適用後? 適用前?)
– ちょっとレンダラとは外れるけど、PNG に gamma 値を導入したことにより生じた不都合 [4]

Refernces

[1] Gamma correction(Wikipedia)
http://en.wikipedia.org/wiki/Gamma_correction

[2] color space
http://www.ousam.com/blog/category/computer-graphics/page/5

[3] ガンマ:滑らかな階調表現のために
http://eclub.eizo.co.jp/lcdtopics/2006/03/post_6.html
ディスプレイにも「くせ」があり、必ずしもγ乗で階調が比例するわけではない.

[4] The Sad Story of PNG Gamma “Correction”
http://hsivonen.iki.fi/png-gamma/
Web における, PNG がガンマ値を持ったことによる不都合.

Advertisements