PHP配列とCSS色表現の相互変換 - 今日も適当ダイアリー に続いて、 relColors に使った関数を公開します。
色の明度や色相を計算するために、いったんRGBで表現された色情報を、HSV色空間に変換した上で計算を行いました。
HSV色空間については HSV色空間 - Wikipedia を参照してください。
RGB から HSV色空間へのコンバート
変換式は、上記したWikipediaに載っているので、それを素直にPHPで書きました。
<?php /** * RGB配列 を HSV配列 へ変換します * * @param array $arr array(r, g, b) ※ r/g/b は 0〜255 の数値 * @param bool $coneModel 円錐モデルにするか * @return array array(h, s, v) ※h は 0〜360の数値、s/v は 0〜255 の数値 */ function RGBtoHSV($arr, $coneModel = false) { $h = 0; // 0..360 $s = 0; // 0..255 $v = 0; // 0..255 $max = max($arr); $min = min($arr); // hue の計算 if ($max == $min) { $h = 0; // 本来は定義されないが、仮に0を代入 } else if ($max == $arr[0]) { // MAX = R // 60 * (G-B)/(MAX-MIN) + 0 $h = 60 * ($arr[1] - $arr[2]) / ($max - $min) + 0; } else if ($max == $arr[1]) { // MAX = G // 60 * (B-R)/(MAX-MIN) + 120 $h = (60 * ($arr[2] - $arr[0]) / ($max - $min)) + 120; } else { // MAX = B // 60 * (R-G)/(MAX-MIN) + 240 $h = (60 * ($arr[0] - $arr[1]) / ($max - $min)) + 240; } while ($h < 0) { $h += 360; } // saturation の計算 if ($coneModel) { // 円錐モデルの場合 $s = $max - $min; } else { if ($max == 0) { // 本来は定義されないが、仮に0を代入 $s = 0; } else { $s = ($max - $min) / $max * 255; } } // value の計算 $v = $max; return array( $h, // H $s, // S $v, // V ); }
HSV から RGB色空間へのコンバート
<?php /** * HSV配列 を RGB配列 へ変換します * * @param array $arr array(h, s, v) ※h は 0〜360の数値、s/v は 0〜255 の数値 * @return array array(r, g, b) ※ r/g/b は 0〜255 の数値 */ function HSVtoRGB($arr) { $r = 0; // 0..255 $g = 0; // 0..255 $b = 0; // 0..255 while ($arr[0] < 0) { $arr[0] += 360; } $arr[0] = $arr[0] % 360; // 特別な場合 if ($arr[1] == 0) { // S = 0.0 // → RGB は V に等しい return array( round($arr[2]), round($arr[2]), round($arr[2]), ); } $arr[1] = $arr[1] / 255; // Hi = floor(H/60) mod 6 $i = floor($arr[0] / 60) % 6; // f = H/60 - Hi $f = ($arr[0] / 60) - $i; // p = V (1 - S) $p = $arr[2] * (1 - $arr[1]); // q = V (1 - fS) $q = $arr[2] * (1 - $f * $arr[1]); // t = V (1 - (1 - f) S) $t = $arr[2] * (1 - (1 - $f) * $arr[1]); switch ($i) { case 0 : // R = V, G = t, B = p $r = $arr[2]; $g = $t; $b = $p; break; case 1 : // R = q, G = V, B = p $r = $q; $g = $arr[2]; $b = $p; break; case 2 : // R = p, G = V, B = t $r = $p; $g = $arr[2]; $b = $t; break; case 3 : // R = p, G = q, B = V $r = $p; $g = $q; $b = $arr[2]; break; case 4 : // R = t, G = p, B = V $r = $t; $g = $p; $b = $arr[2]; break; case 5 : // R = V, G = p, B = q $r = $arr[2]; $g = $p; $b = $q; break; } return array( round($r), // r round($g), // g round($b), // b ); }