2011-11-21 14 views
7

Sono interessante in algoritmi per generare colori "n" graduati tra due colori dati, che generano transizioni uniformi tra ciascuno di essi.Algoritmo per generare colori graduati RGB in PHP

Ho provato a lasciare due canali statici, ad esempio R e G, e il cambiamento incrementale B, ma a volte la differenza tra due colori è più difficile di quella dei vicini.

Voglio controllare diversi algoritmi e analizzare la loro debolezza e punti di forza.


ho scritto questo codice e sembra logica, ma le transizioni tra alcuni colori sono più difficili di quanto tra loro (egbetween 0 e 1 è più difficile di quanto tra 1 e 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 
} 
?> 

Are c'è un algoritmo migliore per fare questo?


porto un esempio: Nel codice sopra ho usato $c1=array(192,5,248); e $c2 = array(142,175,240); e $nc = 10; e ottenuto questa immagine:

graduated colors example

I valori RGB di 0,1,8 e 9 sono:

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

Se si guarda c'è un diference tra i colori vicini di 6,19,1. Ma la transizione visuale tra 0 e 1 è più morbida rispetto alla transizione tra 8 e 9. E per HSV è la stessa cosa. È qualcosa con alcuni colori che rendono la sua transizione più difficile o più morbida.

+0

Quindi .... cosa hai provato finora? – Fosco

+0

Che cosa significa "Ho provato a lasciare due canali statici, ad esempio R e G e il cambiamento incrementale B"? Stai mantenendo R e G uguali e cambia solo B? Funzionerebbe solo se R e G sono uguali nei colori di origine e di destinazione. – mcrumley

+0

Sì @mcrumley, che ho fatto, ma poi ho scoperto che è meglio dividere le differenze tra i canali. Si prega di dare un'occhiata al codice aggiunto. – Memochipan

risposta

4

Nell'immagine seguente potete vedere l'output di un pezzo di codice che ho scritto per confrontare le transizioni tra due colori utilizzando RGB e HSV divisione in fasi uguali dimensioni:

enter image description here

ho trovato le transizioni utilizzando HSV è influenzato dalla tonalità e dipende dalla distanza tra i colori. Se si scelgono due colori con la stessa tonalità, è interessante vedere che le transizioni HSV sono più chiare di quelle in RGB, perché si sta solo giocando con saturazione e valore (nero) e senza aggiungere colori come in 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

In HSV, generare n colori la cui tonalità cambia linearmente dal primo colore al secondo colore. Converti ogni valore HSV in RGB.

+0

Puoi suggerire un modo per farlo in PHP? Guarda il mio codice di esempio qui sopra? Il modo che suggerisci è migliore di quello?Grazie per la tua risposta. – Memochipan

+0

Non c'è niente di specifico per PHP su questo. È semplicemente semplice aritmetica passare da HSV a RGB. Google è tuo amico. Oppure, vedere http://stackoverflow.com/q/3597447/21727 – mbeckish

+0

Non vedo alcun vantaggio dati due colori RGB, convertire in HSV per riconvertire nuovamente in RGB. Ho provato quello che hai detto, ma cambiando V invece di H a passi di 10, e il risultato è esattamente lo stesso del mio codice sopra. – Memochipan

Problemi correlati