2011-11-21 14 views
7

Me resultan interesantes los algoritmos para generar 'n' colores graduados entre dos colores dados, que generan transiciones suaves entre cada uno de ellos.Algoritmo para generar colores graduados RGB en PHP

He intentado dejar dos canales estáticos, por ejemplo R y G, y cambio incremental B, pero a veces la diferencia entre dos colores es más difícil que la de los vecinos.

Quiero verificar diferentes algoritmos y analizar su debilidad y sus fortalezas.


que escribió el código y parece lógica, pero las transiciones entre algunos colores son más difíciles que entre otros (p.ej. entre 0 y 1 es más difícil que entre el 1 y 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 
} 
?> 

Son Hay un mejor algoritmo para hacer esto?


I traer un ejemplo: En el código anterior utilicé $c1=array(192,5,248); y $c2 = array(142,175,240); y $nc = 10; y obtuve esta imagen:

graduated colors example

los valores RGB de 0,1,8 y 9 son:

  • 0 = 192,5,248
  • 1 = 186,24,247
  • 8 = 148.156.241
  • 9 = 142.175.240

Si se mira hay un diference entre los colores vecinos de 6,19,1. Pero la transición visual entre 0 y 1 es más suave que la transición entre 8 y 9. Y para HSV es la misma cosa. Es algo con algunos colores que hace su transición más difícil o más suave.

+0

Entonces .... ¿qué has intentado hasta ahora? – Fosco

+0

¿Qué significa "Intenté dejar dos canales estáticos, por ejemplo R y G, y cambio incremental B"? ¿Estás manteniendo R y G igual y solo cambiando B? Eso funcionaría solo si R y G son iguales en los colores de origen y destino. – mcrumley

+0

Sí @mcrumley, eso hice, pero luego descubrí que es mejor dividir las diferencias entre los canales. Por favor, eche un vistazo al código agregado. – Memochipan

Respuesta

4

En la siguiente imagen se puede ver la salida de un trozo de código que he escrito para comparar las transiciones entre dos colores utilizando RGB y HSV división en pasos de igual tamaño:

enter image description here

me encontré con las transiciones utilizando HSV son afectados por Hue y dependen de la distancia entre los colores. Si elige dos colores con el mismo tono, es interesante ver que las transiciones HSV son más claras que en RGB, porque solo está jugando con saturación y valor (negro) y sin agregar colores como en 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; 
} 
?> 
4

En HSV, genera n colores cuyo matiz cambia linealmente desde el primer color al segundo color. Convierta cada valor de HSV a RGB.

+0

¿Podría sugerir una forma de hacerlo en PHP? Mira mi código de ejemplo de arriba? La forma en que sugieres es mejor que eso?Gracias por tu respuesta. – Memochipan

+0

No hay nada específico de PHP sobre esto. Es simple aritmética cambiar entre HSV y RGB. Google es tu amigo. O bien, consulte http://stackoverflow.com/q/3597447/21727 – mbeckish

+0

No veo ninguna ventaja dados dos colores RGB, convierta a HSV para reconvertirlo nuevamente a RGB. Probé lo que dijiste pero cambié V en lugar de H en pasos de 10, y el resultado es exactamente el mismo que mi código anterior. – Memochipan