減色に使った数式まとめ。

 減色するときに、たとえば、一番近い色をパレットから選ぶときとか、画質を評価する時に、二つの色の差を数値化する必要があります。それを計算する式のまとめ。
 書式はてきとう。"**"は累乗。たぶん間違いな記述込み。

RGBとは

 BMP画像では、1ドットごとに色を、光の三原色であるR,G,Bの三つの数字で表します。 Rは赤光の強さ、Gは緑光の強さ、Bは青光の強さを表します。数字は0〜255で、RGBが0,0,0なら黒い色が、255,255,255なら白い色が出ます。

sRGB→linearRGB

linearRGB = sRGB ** (ガンマ値) + (sRGBが0の時の輝度)
sRGBが255,255,255のとき、linearRGBは1,1,1になるようにする。

 通常BMP画像に使われてるRGBは、むつかしいことしてなけりゃたぶんsRGBという種類のRGBです。で、それを実際にディスプレーに表示されてるそのままのlinearRGBに変換しなきゃいかんです。
 (ガンマ値)は2.2だったり1.8だったり。
 (sRGBが0の時の輝度)ってのは、ディスプレー上でRGBが0,0,0の黒の部分も、実際にはわずかに発光していたり、あと部屋の照明の反射もあったりして、完全な黒じゃ無いわけで、それによる輝度がどれくらいかと言う数字。いわゆる「コントラスト比」は、255,255,255の時の輝度が、0,0,0の時の何倍かを表してるわけです。
 減色ソフトとかで、誤差拡散処理をするときは、画像のRGBをそのまま使うんじゃなくて、linearRGBに変換した上で誤差拡散をしないといけないんだけど、フリーでそれやってるのってあるのかな。
 そうそう、減色だけじゃなくて、画像の縮小とかでも、linearRGBに変換しないでそのままやってるののせいで、黒地に白の文字が潰れて見にくいのなんのって。

linearRGB → XYZ表色系

X=(0.4124*R + 0.3576*G + 0.1805*B)
Y=(0.2126*R + 0.7152*G + 0.0722*B)
Z=(0.0193*R + 0.1192*G + 0.9505*B)

 XYZ表色系と言うのは、RGBの組み合わせじゃ作れない色も表現するために作られた表色系で、いろんな表色系の基礎になる表色系です。なにはともあれとりあえずXYZ。ってな具合です。
 XYZのうち、Yは明度を表していて、XとZが色味を表しています。JPEG圧縮などに使われてるYCbCrのYですね。

XYZ表色系 → L*a*b*表色系

・第1段階
Xn = 0.9505
Yn = 1.0
Zn = 1.0890
・第2段階
X' = (X/Xn)**(1/3)
Y' = (Y/Yn)**(1/3)
Z' = (Z/Zn)**(1/3)
 ただし、XYZが(6/29)^3以下の時は、X'Y'Z'=(1/3)*(29/6)**2*XYZ+(4/29)
・第3段階
L=116*(Y') - 16
a=500*(X'-Y')
b=200*(Y'-Z')

 L*a*b*表色系というのは(中略)。
 簡単にまとめると、「色を三次元空間上に並べたときに、同じ色相の色が放射線状に、同じ彩度の色が円周状になるべく並ぶようにした表色系。」となります。こんなかんじで丸い感じに例えられたりする。
 第2段階の式は実際にはもっと複雑だけど、そこまでする必要はないよね多分。ぜんぜん大丈夫じゃなかったので追加。

L*a*b*表色系 → CIE94色差式。

 二つの色の違いを数値化するときに、L*a*b*表色系の色空間上で、単純に(L*L + a*a + b*b)**0.5とやって、単なる直線距離でやると、微妙に感覚とずれるので、補正式が必要なわけです。
 本当はもっと性能が良いらしいCIEDE2000と言うのを使いたかったけど、計算式が複雑すぎて頭がパンクしたので、簡単なCIE94を使うことにした次第。

・第1段階
L1,a1,b2 … 基準色の色
L2,a2,b2 … 比較色の色
C1 = (a1*a1 + b1*b1)**0.5
C2 = (a2*a2 + b2*b2)**0.5
・第2段階
LE = L2 - L1
aE = a2 - a1
bE = b2 - b1
CE = C2 - C1
E = (LE*LE + aE*aE + bE*bE)**0.5
hE = (E*E - LE*LE - CE*CE)**0.5
・第3段階
Cn = C1 または、(C1*C2)**0.5 もしかしたら、(C1+C2)/2 
Sc = 1 + 0.045*Cn
Sh = 1 + 0.015*Cn
・第4段階
E94 = ( LE**2 + (CE/Sc)**2 + (hE/Sh)**2 )**0.5

 C1やC2は、その色の彩度、CEは二つの色の彩度の差。hEは、二つの色の色相の差を表します。
 どういう補正をしてるのかというと、「色が鮮やかなほど、色相、彩度の変化の色差を小さく」してます。ScとShがその補正のきき具合を表します。人間の目は、鮮やかなほど色味の変化に鈍くなるらしいです。