在PHP中计算两种颜色之间的平均颜色,使用索引号作为参考值

Posted

技术标签:

【中文标题】在PHP中计算两种颜色之间的平均颜色,使用索引号作为参考值【英文标题】:Calculating the average color between two colors in PHP, using an index number as reference value 【发布时间】:2011-05-30 09:22:04 【问题描述】:

php 中,我试图计算不同十六进制颜色之间的平均颜色(十六进制)。但是,我还需要能够提供介于 0.0 和 1.0 之间的索引号。

例如:

我有

$color1 = "#ffffff" 
$color2 = "#0066CC"

如果我要编写一个函数来获取平均颜色并提供 0.0 作为索引号,则该函数需要返回“#ffffff”。如果我提供 1.0 作为索引号,则该函数需要返回“#0066CC”。但是,如果我提供 0.2,该函数将需要返回两种颜色之间的平均颜色,但仍然更接近$color1 而不是$color2。如果我提供索引号 0.5,我将得到两种颜色的准确平均颜色。

我已经尝试了好几天了,但我似乎无法弄清楚!因此,任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

为了讨论的目的,我们假设每种颜色都有一个“值”。然后,你想要的就很简单了:

$index = 0.2;
$val1 = get_value_of_color($color1);
$val2 = get_value_of_color($color2);
$newval = $val1 * $index + $val2 * (1 - $index);
$newcolor = get_color_from_value($newval);

所以,最难的部分是弄清楚每种颜色的“价值”是什么。

您可以使用简单的 RGB 值,其中每种颜色的“值”是一组三个整数:

function get_value_of_color($color) 
    // assume $color is in the form #xxxxxx
    return array(
        hexdec(substr($color, 1, 2)),
        hexdec(substr($color, 3, 2)),
        hexdec(substr($color, 5, 2)),
    );


function get_color_from_value($value) 
    return sprintf('#%02x%02x%02x', $value[0], $value[1], $value[2]);

这里需要对每个数组元素分别进行乘法和加法。我认为在这一点上应该很容易制作一个简单易用的函数来自己混合颜色。

如果这不是您所需要的,那么您可以使用 HSL 值或其他更适合您的应用程序的指标。这个想法将保持不变。

【讨论】:

删除了我的答案,因为它根本不能很好地处理十六进制 RGB 颜色的设计方式。你的要简单得多。 把我的答案也删了,学习了sprintf函数,谢谢!对于此代码,这意味着您不必检查十进制数是否只有 1 位,因为您用 0 填充它。 大家好!好吧,老实说,我使用了安迪的版本,效果很好!!正是我需要的……但是你们是说我应该改用乔恩的版本吗??? @Roel:使用任何你喜欢的东西。我的回答故意比功能更具解释性,所以我并不是说这是复制/粘贴的最佳解决方案。【参考方案2】:

我不确定它是否会编译,但如果你想要这背后的数学,它会是这样的:

为简单起见,始终让$color1 大于$color2

$dec1 = hexdec($hex_color1);
$dec2 = hexdec($hex_color2);

$dec1 = ($dec1 < $dec2) ? $dec1^=$dec2^=$dec1^=$dec2 : $dec1;

$new_hex_color = dechex($dec1 - ($dec1 - $dec2)*index_number)

【讨论】:

@Junky:这样的代码看起来很漂亮……如果您不需要维护它。 有什么需要维护的?这是一条线?!【参考方案3】:

你可以试试:

function color_avg($color1,$color2,$factor) 

        // extract RGB values for color1.
        list($r1,$g1,$b1) = str_split(ltrim($color1,'#'),2);
        // extract RGB values for color2.
        list($r2,$g2,$b2) = str_split(ltrim($color2,'#'),2);

        // get the average RGB values.
        $r_avg = (hexdec($r1)*(1-$factor)+hexdec($r2)*$factor);
        $g_avg = (hexdec($g1)*(1-$factor)+hexdec($g2)*$factor);
        $b_avg = (hexdec($b1)*(1-$factor)+hexdec($b2)*$factor);

        // construct the result color.    
        $color_avg = '#'.sprintf("%02s",dechex($r_avg)).
                        sprintf("%02s",dechex($g_avg)).
                        sprintf("%02s",dechex($b_avg));


        // return it.
        return $color_avg;

See it

【讨论】:

+1 表示str_split。我不知道 PHP 有第 574 个字符串操作函数!【参考方案4】:

我用上面提到的函数试过这个:

/* 24-bit RGB */
/* (a + b) / 2 = ((a ^ b) >> 1) + (a & b) */
function averageRGB($a, $b)
  return ((($a ^ $b) & 0xfffefefe) >> 1) + ($a & $b);


$index = 0.5;
$val1 = get_value_of_color('#FFFFFF');
$val2 = get_value_of_color('#000000');

$aIndexed = array();

for($i=0; $i < 3; $i++)
     if($index == 0.5)
        $aIndexed[$i] = averageRGB($val1[$i],$val2[$i]);
     else
        $aIndexed[$i] = $val1[$i] * $index + $val2[$i] * (1 - $index);
         


echo get_color_from_value($aIndexed);

【讨论】:

【参考方案5】:
function colorDiff($color1,$color2) 
    $color1=    ltrim($color1,'#');
    $color2=    ltrim($color2,'#'); 
    $red1 =     hexdec(substr($color1,0,2));
    $green1 =  hexdec(substr($color1,2,2));
    $blue1 =    hexdec(substr($color1,4,2));
    $red2 =     hexdec(substr($color2,0,2));
    $green2 =  hexdec(substr($color2,2,2));
    $blue2 =   hexdec(substr($color2,4,2));
    $red =  dechex(round(($red1+$red2)/2));
    $green =    dechex(round(($green1+$green2)/2));
    $blue =     dechex(round(($blue1+$blue2)/2));
    if (strlen($red) == 1)  $red = '0'.$red; 
    if (strlen($green) == 1)  $green = '0'.$green; 
    if (strlen($blue) == 1)  $blue = '0'.$blue; 
    $newcolor = '#'.$red.''.$green.''.$blue;
    return $newcolor;

【讨论】:

【参考方案6】:

或者使用数组作为输入:

 $color_arr =
array('#FF0000','#0000FF','#FF0000','#0000FF','#0000FF','#0000FF');
$newcolor = colorDiffArr($color_arr); foreach ($color_arr as $color) 
    echo '<div style="display:block; background:'.$color.';"
 bgcolor="'.$color.'; width:10px; height:10px;">'.$color.'</div>'; 
 echo '<div style="display:block; background:'.$newcolor.';"
 bgcolor="'.$newcolor.'; width:10px;
 height:10px;">'.$newcolor.'</div>';
 function colorDiffArr($color_arr)     
       $red = 0; $green = 0; $blue = 0;
       foreach ($color_arr as $color)          
          $color= ltrim($color,'#');
          $red+=hexdec(substr($color,0,2));         
          $green+=hexdec(substr($color,2,2));       
          $blue+=hexdec(substr($color,4,2));    
       $red =       dechex(round(($red)/count($color_arr)));    
          $green =
    dechex(round(($green)/count($color_arr)));  $blue =
    dechex(round(($blue)/count($color_arr)));       if (strlen($red) == 1) 
 $red = '0'.$red;      if (strlen($green) == 1)  $green = '0'.$green; 
    if (strlen($blue) == 1)  $blue = '0'.$blue;   $newcolor =
 '#'.$red.''.$green.''.$blue;   return $newcolor; 

【讨论】:

以上是关于在PHP中计算两种颜色之间的平均颜色,使用索引号作为参考值的主要内容,如果未能解决你的问题,请参考以下文章

AS3两种颜色之间的平均颜色(我的版本)

颜色渐变的RGB计算

PHP中颜色之间的“距离”

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

如何计算位图的平均 rgb 颜色值

在javascript中平均2个十六进制颜色