Алгоритм генерации цветных цветов RGB в PHP

Мне интересно в алгоритмах генерировать «n» градуированные цвета между двумя заданными цветами, которые генерируют плавные переходы между каждым из них.

Я попытался разрешить статические два канала, например R и G, и инкрементное изменение B, но иногда разница между двумя цветами сложнее, чем у соседей.

Я хочу проверить разные алгоритмы и проанализировать их слабость и сильные стороны.


Я написал этот код, и он кажется логичным, но переходы между некоторыми цветами сложнее, чем между другими (например, между 0 и 1 сложнее, чем между 1 и 2):

<?php $c1 = array(128,175,27); // Color 1 $c2 = array(255,255,140); // Color 2 $nc = 5; // Number of colors to display. $dc = array(($c2[0]-$c1[0])/($nc-1),($c2[1]-$c1[1])/($nc-1),($c2[2]-$c1[2])/($nc-1)); // Step between colors for ($i=0;$i<$nc;$i++){ echo '<div style="width:200px;height:50px;background-color:rgb('.round($c1[0]+$dc[0]*$i).','.round($c1[1]+$dc[1]*$i).','.round($c1[2]+$dc[2]*$i).');">'.$i.'</div>'; // Output } ?> 

Есть ли лучший алгоритм для этого?


$c1=array(192,5,248); пример: В приведенном выше коде я использовал $c1=array(192,5,248); и $c2 = array(142,175,240); и $nc = 10; и получил это изображение:

пример градуированных цветов

Значения RGB 0,1,8 и 9:

  • 0 = 192,5248
  • 1 = 186,24,247
  • 8 = 148 156 241
  • 9 = 142 175 240

Если вы посмотрите, есть разница между соседними цветами 6,19,1. Но визуальный переход между 0 и 1 более мягкий, чем переход между 8 и 9. И для ВПГ это одно и то же. Это что-то с некоторыми цветами, которые делают его переход труднее или мягче.

В HSV генерируйте n цветов, оттенок которых изменяется линейно от первого цвета до второго цвета. Преобразуйте каждое значение HSV в RGB.

На следующем рисунке вы можете увидеть вывод фрагмента кода, который я написал, для сравнения переходов между двумя цветами с использованием разделения RGB и HSV с шагом равного размера:

введите описание изображения здесь

Я обнаружил, что переходы с использованием HSV подвергаются воздействию Hue и зависят от расстояния между цветами. Если вы выберете два цвета с тем же оттенком, интересно увидеть, что переходы HSV более понятны, чем в RGB, потому что вы играете только с насыщенностью и значением (черный) и без добавления цветов, например, в RGB.

 <?php // Configuration. $nc = 6; // Number of colors. $w = 300; // Width of divs. $a = 50; // Height of divs. // Colors /* In RGB */ $c1 = array(rand(0,255),rand(0,255),rand(0,255)); $c2 = array(rand(0,255),rand(0,255),rand(0,255)); //$c1 = array(128,175,27); // Color 1: Whit these colors is not change. //$c2 = array(255,255,140); // Color 2: Whit these colors is not change. // $c1 = array(0,0,0); // Color 1: White. // $c2 = array(255,255,255); // Color 2: Black. /* In HSV */ $h3 = array(rand(0,360),rand(0,100),rand(0,100)); $h4 = array(rand(0,360),rand(0,100),rand(0,100)); //$h3 = array(145,50,50); // Color 3: To see the influence of Hue. //$h4 = array(145,0,100); // Color 4: To see the influence of Hue. // HTML $html .= '<div style="margin:auto;width:'.($w*2).'px;">'; // RGB to RGB split $c = graduateRGB($c1,$c2,$nc); $html .= customHTML($w,$a,$c,'RGB->RGBs'); // RGB to HSV split $h1 = RGBtoHSV($c1); $h2 = RGBtoHSV($c2); $h = graduateHSV($h1,$h2,$nc); $html .= customHTML($w,$a,$h,'RGB->HSVs'); // HSV to HSV split $h = graduateHSV($h3,$h4,$nc); $html .= customHTML($w,$a,$h,'HSV->HSVs'); // HSV to RGB split $c3 = HSVtoRGB($h3); $c4 = HSVtoRGB($h4); $c = graduateRGB($c3,$c4,$nc); $html .= customHTML($w,$a,$c,'HSV->RGBs'); // Output $html .= '</div>'; echo $html; /* FUNCIONES DE GRADUACIÓN */ // Dados dos colores RGB (0-255,0-255,0-255) y un número de colores deseados, regresa un array con todos los colores de la gradación. function graduateRGB($c1,$c2,$nc){ $c = array(); $dc = array(($c2[0]-$c1[0])/($nc-1),($c2[1]-$c1[1])/($nc-1),($c2[2]-$c1[2])/($nc-1)); for ($i=0;$i<$nc;$i++){ $c[$i][0]= round($c1[0]+$dc[0]*$i); $c[$i][1]= round($c1[1]+$dc[1]*$i); $c[$i][2]= round($c1[2]+$dc[2]*$i); } return $c; } // Dados dos colores HSV (0-360,0-100,0-100) y un número de colores deseados, regresa un array con todos los colores de la gradación en RGB. (Hay un detalle con esta función y es que la transición se podría hacer por el lado contrario del círculo cromático) function graduateHSV($h1,$h2,$nc){ $h = array(); $dh = array(($h2[0]-$h1[0])/($nc-1),($h2[1]-$h1[1])/($nc-1),($h2[2]-$h1[2])/($nc-1)); for ($i=0;$i<$nc;$i++){ $h[$i][0]= $h1[0]+$dh[0]*$i; $h[$i][1]= $h1[1]+$dh[1]*$i; $h[$i][2]= $h1[2]+$dh[2]*$i; $h[$i] = HSVtoRGB($h[$i]); } return $h; } /* FUNCIONES DE CONVERSIÓN. */ // Convierte a HSV (0-360,0-100,0-100) colores en RGB (0-255,0-255,0-255). function RGBtoHSV(array $rgb) { $f = 0.00000001; // Factor de corrección para evitar la división por cero. list($R,$G,$B) = $rgb; $R = $R==0?$f:$R/255; $G = $G==0?$f:$G/255; $B = $B==0?$f:$B/255; $V = max($R,$G,$B); $X = min($R,$G,$B); $S = ($V-$X)/$V; $V_X = $V-$X==0?$f:$V-$X; $r = ($V-$R)/($V_X); $g = ($V-$G)/($V_X); $b = ($V-$B)/($V_X); if ($R == $V) $H = $G==$X?(5+$b):(1-$g); elseif ($G == $V) $H = $B==$X?(1+$r):(3-$b); else $H = $R==$X?(3+$g):(5-$r); $H /= 6; $H = round($H*360); $S = round($S*100); $V = round($V*100); return array($H, $S, $V); } // Convierte a RGB (0-255,0-255,0-255) colores en HSV (0-360,0-100,0-100). function HSVtoRGB(array $hsv) { list($H,$S,$V) = $hsv; $H = $H/360; $S = $S/100; $V = $V/100; //1 $H *= 6; //2 $I = floor($H); $F = $H - $I; //3 $M = $V * (1 - $S); $N = $V * (1 - $S * $F); $K = $V * (1 - $S * (1 - $F)); //4 switch ($I) { case 0: list($R,$G,$B) = array($V,$K,$M); break; case 1: list($R,$G,$B) = array($N,$V,$M); break; case 2: list($R,$G,$B) = array($M,$V,$K); break; case 3: list($R,$G,$B) = array($M,$N,$V); break; case 4: list($R,$G,$B) = array($K,$M,$V); break; case 5: case 6: //for when $H=1 is given list($R,$G,$B) = array($V,$M,$N); break; } $R = round($R*255); $G = round($G*255); $B = round($B*255); return array($R, $G, $B); } // Función con un HTML de muestra para la visualización de colores, podría ser cualquier otro. function customHTML($w,$a,$c,$header){ $html = '<div style="float:left;text-align:center;"><h2>'.$header.'</h2>'; foreach ($c as $color){ $html .= '<div style="width:'.$w.'px;height:'.$a.'px;background-color:rgb('.$color[0].','.$color[1].','.$color[2].');">RGB '.$color[0].','.$color[1].','.$color[2].'</div>'; } $html .= '</div>'; return $html; } ?>