はじめに
PNG はディスプレイガンマを意識した画像ファイルフォーマットです。メタデータにガンマ補正の値を含める事ができます。
そのメタデータとしてのガンマ補正を解説します。
ガンマ補正自体の解説はこちらをどうぞ。
PNG のガンマ値
PNG ファイルは内包する RGB データのリニア輝度からのガンマ補正値を、メタデータとして持つ事ができます。
ファイル形式では gAMA チャンクが相当します。ImageMagick の identify で確認できます。
% identify -verbose sample.png | grep gamma
png:gAMA: gamma=0.45455 (See Gamma, above)
歴史的な事情
今どきのプラットフォームでは画像のRGB値と物理的な色の対応を sRGB規格に合わせる事が多いです。
そのsRGBによる輝度変換はガンマ(γ, gamma)変換の係数"2.2"でおよそ近似できます。
ところが環境によってこのガンマ値が異なる可能性があり、今となっては古い例ですが、Macintosh がガンマ1.8環境だった頃に、Windows で作った画像ファイルを Macintosh で表示すると色の明るさが微妙に変わってしまいました。
![PNG-NoGamma.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F1798%2F975300ff-2655-8942-074f-f2597b145fbb.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=adba11b86ee1f9e16f37b391c28f1d4d)
そこで、PNG ファイルのメタデータである gAMA チャンクに 1.0/2.2 を書き置く事で、他の OS (PNG 仕様策定当時のガンマ値が違う環境だと Macintosh, SGI IRIX、 NeXT 等) で表示する際に、その gAMA 値で補正すれば物理的に同じ明るさの色が表示できる。といった仕組みです。
![PNG-gAMA.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F1798%2F8c0c5bf5-7f09-e8f1-0ef9-f3b62c4d3675.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=83d40bbb93604111d78c3534c6edcb52)
ただし、gAMA チャンクによる輝度補正だと雑になるので、正確に色を再現したい場合は sRGB チャンクや iCCP チャンクを使うよう PNG仕様に書かれています。
gAMAチャンクはもはや歴史的な遺物と言いたい所ですが、仕様として残っているので今でもエンコーダ、デコーダ共に対応する必要がありますし、今時のエンコーダでも gAMA チャンクが入る事が多いです。
gAMA がない場合
gAMA, sRGB, iCCP チャンクのいずれもない PNG ファイルの RGB ガンマ値(正確には表示階調特性,EOTF)は実は環境依存です。なので、その場合は PNG ファイルがどの環境で作られかに合わせて、表示する際に補正する必要があるのですが、現実的でないので、通常は 1.0/2.2 決め打ちで処理する事が多いはずです。
備考
画像ビューア(ブラウザ含む)によっては gAMA を無視したり、カラー画像では使うけどグレースケールは無視とか、16bit は駄目、変換時に中途半端に使われる等といった不具合に散々悩まされてきました。
gAMA には1.0/2.2 しか入れないよう運用するのが無難でしょう。