豪鬼メモ

一瞬千撃

デジカメの画像データの色空間を再検討

現像済みの写真データを保存するにあたっては、色空間を選択せねばならない。今までは特に深いことを考えずにsRGBやAdobe RGBを選択していたが、そのあたりをちょっと調べてみた。結論としては、これからはProPhoto RGBを使っていこうということに。
f:id:fridaynight:20170117212725p:plain


Google PhotosにTIFFデータを保存するとお得だという話を以前の記事に書いた。RAWデータを保存するのであれば、色空間は後で現像する際に選択するので現時点では考えなくてよいが、JPEGTIFFを保存するならば、それらを生成する際に色空間を指定することになる。ここで、私も含む多くの人はデフォルト的な位置づけであるところのsRGBを選択しているわけだが、長期的に考えるとこれはあまりよくない。上の図を見るとわかるが、表現できる色が狭すぎるのだ。sRGBはJPEGのデフォルトの色空間なのでプロファイルを埋め込まなくても表示できるし、Webブラウザを含むほぼすべての表示環境で同じように表示できるという利点がある一方、濃い緑や赤が色飽和しやすいという欠点がある。このサイトの説明が非常にわかりやすい。Macbook Proも2016後期版からsRGBを超えたIDC-P3色空間の色を表示できるようになったらしいし、量子ドット液晶やら有機LEDやらを搭載したディスプレイも多数出てきているので、すでに広い色空間のことをちゃんと考えることに実用的な意味が生じている。

さて、このsRGBとか呼ばれてJPEG標準に採用されてたりITU Rec 709とか呼ばれてHDテレビの標準になってたりする仕様だが、留意すべき特徴がある。RGBの各チャンネルにおいて、輝度を線形に表現して保持するのではなく、下の絵の青線のようなカーブの関数を適用した値を保持するのだ。すなわち、線形輝度が0.00313より下ならそのままの値を、それ以上ならガンマ2.2(=1/2.2乗)をもとにした値に変換して保持する。ガンマ補正して明るくしたデータを保持する理由は、暗部の輝度の差を認識しやすいという人間の認知特性に合わせて、暗い部分のトーンに詳細な階調を割り当てたいかららしい。しかし最暗部を持ち上げてもノイズを拾うだけなので、そこは線形でいいやと。ルールが複雑化して嫌な感じだが、いかにも現場の技術者が考えた感じの実用的な仕様である。
f:id:fridaynight:20170117214727p:plain

sRGBに次いで有名なのがAdobe RGB 1998だ。多くのデジカメでも撮って出しJPEGでの色空間として選択可能であり、私のE-M10もサポートしているので、気まぐれに選択することがある。Adobe RGBでは、赤と青の純色はsRGBと同じだが、緑がより広くなっている。よって、対応したディスプレイやプリンタを使えば、sRGBより深い、濃い緑を表現することができる。しかし、赤と青に関しては全く利点がないとも言える。もう一つ面白い特徴は、Adobe RGBの輝度エンコーディングでは、sRGBと違って全範囲でガンマ2.2が適用されるということだ。マジックナンバーを嫌う数学者肌の人が考えたんだろうか。

そして、Appleが最近押しているのがIDC-P3だ。青の純色はsRGBと同等だが、赤と緑がより広くなっている。実際にそれを表示できるディスプレイが普及してきているので、今ならAdobe RGBよりも実用性がありそげ。こちらはガンマ2.6をベースとして、最暗部はsRGBと同様に線形になる輝度エンコーディングを採用している。これに関して注意すべきは、LightroomでDisplay P3として選択できる設定は、IDC-P3をベースにガンマ値を2.2にした通称Apple P3なる色空間だということだ。既存のディスプレイとの互換性を重視した結果だとかなんとか。ややこしい。

Lightroomがサポートする最大の色空間であり、Lightroomの内部処理でも利用されているのがProPhoto RGBである。人間が認識できる色の90%を表現できるらしい。Photoshop等にデータを引き渡す際やそこでの作業用の色空間としてもProPhoto RGBを使うことをAdobeは推奨している。ということで保存データの色空間はProPhoto RGB一択だねという結論になる。ProPhotoの輝度エンコーディングは全域でガンマ1.8である。この点もわかりやすくてよい。

そもそも、わざわざ狭くした色空間の仕様が乱立してしまったのは、8ビットチャンネル時代に、その限られた情報量で所望の色と階調をいかに美しく表現するかという努力が各方面でなされたからだろう。16ビットTIFFを保存すると決めたなら、もうトーンジャンプのことはあまり心配しなくていいので、ケチケチせずに広めの色空間を使えばいいのだ。逆に言えば、8ビットTIFFJPEGを保存するならば、やはり表示環境に合わせて選択することになろう。Webに上げるならsRGBだし、Adobe RGB対応ディスプレイで見るならAdobe RGBだし、Apple押しならDisplay P3にするのもいいだろう。でも将来の表示形式を今の保存時に規定するのはあまり得策ではないよね。


残念ながらあまり家計に余裕がないので、私はsRGBを超える色域の表示環境を持っていない。なので、色域が広いことの利点を現時点では全く享受できていない。できることと言えば、同じ色に見える画像のRGBの数値が色空間によって異なるのを確認して唸ることぐらいだ。ただ、それだと寂しいので、なんとか頑張って可視化してみよう。

サトちゃんをVividで現像してみた。この鮮やかな橙色は色飽和しがちであるからして、各々の色空間でどうなるか比べてみたい。まずはsRGB。
f:id:fridaynight:20170123014607j:plain

Adobe RGB。少なくとも橙色の見た目は変わらないはず。
f:id:fridaynight:20170123014628j:plain

Display P3。広色域のディスプレイだと、緑色と橙色の発色がよくなっているかもしれない。
f:id:fridaynight:20170123014637j:plain

ProPhoto RGB。広色域のディスプレイだと、緑色と橙色の発色がよくなっているかもしれない。
f:id:fridaynight:20170123014648j:plain

私のMacbook Pro 2012年版では全く区別がつかないのだが、P3対応をうたっているMacbook Pro 2016年版だと、サトちゃんの手の緑の違いがよくわかる。橙色の部分はあんまり違いがわからないけど、ちょっとだけ濃く見える気もする。なお、現時点ではAndroidLinuxChromeブラウザはICCプロファイルの対応が適切になされていないので、sRGB以外の画像はちゃんと表示されない。Mac版では対応しているので、今後に期待したい。


JPEG画像に埋め込まれたプロファイルを剥奪してみる。sRGBとして解釈されるので、sRGBの場合は全く変わらないはず。
f:id:fridaynight:20170123014750j:plain

剥奪Adobe RGB。緑成分が薄くなるので、補色であるマゼンタに寄った感じになる。また、最暗部は明るくなる。
f:id:fridaynight:20170123014800j:plain

剥奪Display P3。緑と赤がちょっと薄くなる。明るさはあまり変わらない。
f:id:fridaynight:20170123014811j:plain

剥奪ProPhoto RGB。全体的に色が薄くなり、そして暗くなる。
f:id:fridaynight:20170123014826j:plain

プロファイルを外すことで色空間の違いが視認できるとは、皮肉なものだ。


色空間の違いを明確化するもう一つの方法がある。作業用色空間を変えて、彩度を操作するのだ。最初の例では、PhotoProで現像した画像の彩度(=HSLのSチャンネル)にガンマ0.5を適用している。1以下のガンマ補正は中間的な値を下限側に寄せる効果があるだけで、変域の上限の値には何も影響がない。にもかかわらずこの例ではサトちゃんの色が全体的に薄くなっているので、つまり彩度が飽和してはいないということが確認できる。
f:id:fridaynight:20170119153755j:plain

一方、sRGBで現像したデータで同じことをしてみると、サトちゃんの色が全く薄くならない。色が薄くなっていないということは、彩度が上限に達しているかそれに近いことを意味している。つまり色飽和しているということ。これでやっと高級ディスプレイを持っていなくてもProPhotoの良さがわかる。頭ではわかるが心ではわからないという事例の典型ではあるが。
f:id:fridaynight:20170119154329j:plain


階調の違いに着目すべく、グレースケール画像で比較してみよう。まず、グレースケール画像を用意して、ProPhoto RGBの画像を出力する。
f:id:fridaynight:20170118105212j:plain

次に、sRGBで出力して、ICCプロファイルを剥奪したもの。当然、プロファイルがなくても同じように表示される。
f:id:fridaynight:20170118105412j:plain

剥奪Adobe RGB。最暗部は明るくなる。別タブで開いて上の例と切り替えながら見れば違いがわかるはず。
f:id:fridaynight:20170118105552j:plain

剥奪Display P3。sRGBとほとんど全く同じ。やはりガンマ値はIDC-P3仕様の2.6でなく、2.2だということが確認できる。
f:id:fridaynight:20170118105733j:plain

剥奪ProPhoto RGB。全体的に暗くなる。ガンマ値が2.2よりは低いということがわかる。
f:id:fridaynight:20170118105919j:plain


ImageMagickを使って、ProPhoto RGBの画像から、sRGBの画像を得てみる。最も普通の方法は、ICCプロファイルを使うことだ。最初にstripオペレータ入力データのICCプロファイルを剥ぎ取った上で、1回目のprofileオペレータで明示的にProPhotoRGBを付与し、2回目のprofileオペレータでsRGBに変換している。実際には、ICCプロファイルはすでに入力内にあるので、剥奪しないで2回目のオペレータだけをかけても同じことである。

convert -strip \
-profile /usr/share/color/icc/ProPhotoRGB.icc \
-profile /usr/share/color/icc/sRGB.icc \
bridge-pro.tif bridge-pro-srgb.jpg

すると、こうなる。色飽和した領域以外は、ほぼ同じ画像が得られているはず。
f:id:fridaynight:20170118111400j:plain

ProPhotoのエンコーディングガンマ1.8という仕様を確認するため、こんなトリッキーな方法もある。1/1.8=0.5555なので、線形RGB色空間とみなした上で、ガンマ補正0.5555をかけてから、それをsRGBに変換する。

convert -strip \
-set colorspace RGB \
-level '0,100%,0.5555' \
-colorspace sRGB \
bridge-pro.tif bridge-pro-gamma.jpg

すると、こうなる。こちらも、ほぼ同じ画像が得られているはず。
f:id:fridaynight:20170118112529j:plain


ProPhoto RGBで現像した画像は、後でsRGBに変換することもできる。まずはProPhotoの元データをそのままJPEGにしたもの。
f:id:fridaynight:20170119111144j:plain

こちらは、ProPhotoの元データをsRGBに変換してからJPEGにしたもの。
f:id:fridaynight:20170119111324j:plain

もういっちょ、ProPhoto RGB現像。
f:id:fridaynight:20170124014711j:plain

そのsRGB変換。
f:id:fridaynight:20170124014722j:plain

広い色域対応のディスプレイで見た場合、ProPhotoの例の方がsRGBの例よりも鮮やかに見える部分があるだろう。そうでないsRGB対応の普通のディスプレイで見た場合、両者はほとんど同じに見えるだろう。P3対応のMacbook Proで見た限りでは、上の例の男性の袖の赤や、下の例の娘のかんざしの赤には違いが見られる。色飽和した部分がどう表現されるかはレンダリングエンジン次第だけども。

広い色空間のデータを狭い色空間に変換する限りにおいては、情報が欠損することはない。狭い色空間の方が同じビット数で狭い変域を表しているのだから階調が緻密であって、同じビット幅の広い色空間のデータから狭い色空間に変換すると、階調が荒くなるという欠点はある。しかし、保存用データが16ビットTIFFで閲覧用データが8ビットJPEGである典型的なユースケースでは、階調が問題になることはないだろう。


ProPhoto RGBの16ビットTIFFGoogle Photosに保存することにした。アップロードした元データ自体は無加工で保存されるので、Lightroomが出力したプロファイル付きのファイルをアップロードすれば問題ない。残る懸念は、閲覧時のサムネール画像にちゃんとプロファイルが埋め込まれて意図通りに表示されるかである。結論から言えば、現状ではサムネールの処理はプロファイルに対応していない。各種色空間の画像はこんな風に表示されてしまう。
f:id:fridaynight:20170118113544p:plain

ただし、拡大するとちゃんと見えるようになる。元データ経由で処理している時はこうなるのかな。
f:id:fridaynight:20170118113720p:plain

当然ながら、サムネール画像を作る時も、元データのプロファイルを埋め込むべきである。プロファイルすら削ってデータ量を小さくしたいならば、色空間をsRGBに変換してから出力すべきだ。まあこれは表示方法だけの問題なので、いずれ改善されるとは思う。元データの管理が満足であれば問題ないだろう。

なお、16ビットTIFFを12ビットJPEG2000に変換したデータを大量に持っている私としては、それをプロファイル付きの16ビットTIFFに戻すバッチ処理が必要になる。JPEG2000は色空間を明示する仕様が確定していないので、さしあたってはICCProfileNameというEXIF属性にプロファイル名を埋め込んで保存しているのが現状だ。以前の記事も述べた変換スクリプトでその対応は行っている。


21世紀も16%過ぎたのだから、旧世代の貧乏くさいsRGBと8ビットJPEGからはそろそろ卒業したい。サトちゃんの鮮明なオレンジをきちんと味わいたいではないか。ProPhoto RGBの16ビットTIFFでウッボー。