iOS 10 からデフォルトとして使用されている 拡張sRGB色空間 について説明します。
はじめに、sRGB色空間 (not 拡張) とは
下のCIE色度図 1 のうち、点線の三角形で囲まれた部分がsRGB色空間です。
色のついている範囲が人が見ることのできるすべての色なのですが、その中の特定の範囲を限定してsRGB色空間と呼んでいます。


sRGB色空間はコンピューターの世界で一般的によく使われており、色空間について特に指定のないときは暗にこのsRGB色空間を指していることが多いです。
CIE色度図やRGB色空間の詳しい説明は別の記事に書いたのでこちらをご覧ください。
RGB値だけでは色は1つに定まらない
https://qiita.com/mishimay/items/e1e2f536068c3dafd01c
sRGB色空間の問題点
上のCIE色度図を見てもわかる通り、sRGB色空間は人が見ることのできるすべての色をカバーしていません。
これを解決するのが拡張sRGB色空間です。
拡張sRGB色空間 (Extended sRGB Color Space) とは
sRGB色空間では、R、G、Bそれぞれについて 0.0~1.0
(または 0~255
) の範囲で数値を指定することで特定の色を表現しました。
一方、 拡張sRGB色空間はマイナスの数値や1を超える数値を許容します。 これにより既存のsRGB色空間での指定値はそのままに、さらにその外側のあらゆる色を表現可能になります。
使用方法
iOS 10.0 以上から使用可能です 2。
UIColorのデフォルトがこの拡張sRGB色空間なので 3、特に意識することなく使うことができます。
実際、今現在意識せず使っている方が多いと思います。
以下のコードは iOS 9 と iOS 10 で異なる値を出力します。
let color = UIColor(red: 1.2, green: -0.3, blue: 100, alpha: 1)
print(color)
iOS 9
UIDeviceRGBColorSpace 1 0 1 1
iOS 10
UIExtendedSRGBColorSpace 1.2 -0.3 100 1
iOS 9 では 0~1
の範囲に値が丸められている一方で、iOS 10 では表記がUIExtendedSRGBColorSpace
となり負の値も大きな値もそのままであることが分かります。
他色空間からの変換方法
iOSには別のRGB色空間への変換メソッドが用意されています 4 。
例として Display P3 色空間から拡張sRGB色空間へ変換するコードを書いてみましょう。
下図 1 にあるように Display P3 色空間とsRGB色空間では緑色部分にある頂点の位置がかなりずれています。


Display P3 色空間における緑色はsRGB色空間の外側に存在する、つまり拡張sRGB色空間においてRGBの値が 0~1
に収まらないはずです。
それを確かめてみましょう。
let p3Color = UIColor(displayP3Red: 0, green: 1, blue: 0, alpha: 1)
let extendedSRGBColorSpace = CGColorSpace(name: CGColorSpace.extendedSRGB)!
let extendedSRGBColor = p3Color.cgColor.converted(to: extendedSRGBColorSpace, intent: .defaultIntent, options: nil)
print(extendedSRGBColor)
iOS 10
[<CGColorSpace 0x600003d69140> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( -0.511767 1.01831 -0.310667 1 )
このように Display P3 色空間における (R: 0, G: 1, B: 0)
は、拡張sRGB色空間では (R: -0.511767, G: 1.01831, B: -0.310667)
となりました。
予想通り 0~1
の範囲を超えています。
Gは約1.02と微増の一方で、Rは約-0.5とかなり大きくマイナスに振れているのが興味深いです。
環境
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0