在PHP中生成RGB渐变色的算法

在PHP中生成RGB渐变色的算法

问题描述:

我很感兴趣的算法是在两个给定颜色之间生成'n'渐变颜色,这些颜色在每个颜色之间生成平滑过渡。在PHP中生成RGB渐变色的算法

我试着让静态两个通道,例如R和G,以及增量变化B,但有时两种颜色之间的差异比邻居更难。

我想检查不同的算法并分析它们的弱点和强度。


我写了这个代码,它似乎逻辑,但一些颜色之间的过渡比其他之间更硬(egbetween 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);$c2 = array(142,175,240);$nc = 10;和获得该图像的代码:

graduated colors example

的0,1,8的RGB值和9是:

  • 0 = 192,5,248
  • 1 = 186,24,247
  • 8 = 148156241
  • 9 = 142175240

如果你看那里是6,19,1相邻颜色之间的性差异。但0到1之间的视觉过渡比8到9之间的过渡要柔和。对于HSV来说也是一样的。这是一些颜色,使其过渡更硬或更软。

+0

所以....你到目前为止尝试过什么? – Fosco

+0

什么是“我尝试让静态两个通道,例如R和G,以及增量更改B”是什么意思?你是否保持R和G相同,只改变B?这只有在R和G在源和目标颜色相同的情况下才有效。 – mcrumley

+0

是@mcrumley,我做过了,但后来发现最好是分开渠道之间的差异。请看看添加的代码。 – Memochipan

在下面的图片你可以看到一段代码的输出我写信给使用RGB和HSV分裂相等大小的步骤两种颜色之间的对比转换:

enter image description here

我发现使用过渡HSV受色相影响,取决于颜色之间的距离。如果选择具有相同色调的两种颜色,可以发现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; 
} 
?> 

在HSV中,生成n种颜色,其色调从第一种颜色线性变化为第二种颜色。将每个HSV值转换为RGB。

+0

你能建议一种方法来做到这一点在PHP中?看看我上面的示例代码?你建议的方式比这更好?感谢您的回答。 – Memochipan

+0

没有什么PHP特有的。在HSV和RGB之间切换只是简单的算法。 Google是你的朋友。或者,请参阅http://stackoverflow.com/q/3597447/21727 – mbeckish

+0

在给定两种RGB颜色的情况下,我看不到任何优势,请转换为HSV再重新转换为RGB。我测试了你说的话,但是改变了V而不是H,步长为10,结果和我上面的代码完全一样。 – Memochipan