【问题标题】:Interpolating colors in PHP在 PHP 中插值颜色
【发布时间】:2014-01-21 02:10:48
【问题描述】:

我是一名 C++ 程序员,最近开始研究使用 PHP、Javascript 和 HTML 进行 Web 开发。目前我遇到了一些应该非常简单的问题,但没有按我预期的那样工作......

function interpolateColor($corA, $corB, $lerp)
{
$redA = $corA & 0xFF0000;
$greenA = $corA & 0x00FF00;
$blueA = $corA & 0x0000FF;
$redB = $corB & 0xFF0000;
$greenB = $corB & 0x00FF00;
$blueB = $corB & 0x0000FF;

$redC = $redA + (($redB - $redA) * $lerp);
$greenC = $greenA + (($greenB - $greenA) * $lerp);
$blueC = $blueA + (($blueB - $blueA) * $lerp);

return $redC | $greenC | $blueC;
}

我一直在尝试使用此函数根据“优先级”列的值使 HTML 表的行具有不同的颜色,该值从 0 到 10 并除以 10 以形成“lerpAmount” (0-1) 变量。

$cor = interpolateColor(0xFF0000, 0x0000FF, $lerpAmount);

<tr bgcolor="<?=$cor?>">

但是,我得到的颜色看起来不像是红蓝插值...它开始是蓝色的,然后只有一行是绿色,然后变成粉红色并插值成某种形式的棕色,然后变成深蓝色再次,这让我觉得有些不对劲。

提前致谢。

【问题讨论】:

  • 我建议减少 lerpamount 并尝试结果。
  • 您的 $redC、$greenC 和 $blueC 值在乘以 $lerp 后都将是浮点数,因此您正在对一系列浮点数进行 ORing 运算以返回...您可能想要强制转换在执行此操作之前,每个都要再次 int:例如$redC = (int) $redA + (($redB - $redA) * $lerp);
  • 有些值也是负数

标签: php html colors interpolation


【解决方案1】:

您必须在结果颜色和掩码之间进行按位与运算:

$redC = $redA + (($redB - $redA) * $lerp) & 0xFF0000;         // Only Red
$greenC = $greenA + (($greenB - $greenA) * $lerp) & 0x00FF00; // Only Green
$blueC = $blueA + (($blueB - $blueA) * $lerp) & 0x0000FF;     // Only Blue

要获得正确的 RGB 值,然后以十六进制返回颜色,您必须使用以下方法对其进行转换:

$result = dechex($redC | $greenC | $blueC);
return str_pad($result, 6, "0", STR_PAD_LEFT);

(str_pad 是为返回的颜色添加前导零)。

【讨论】:

    【解决方案2】:

    您在这里面临的问题是下溢。我想。不知道这个词对不对XD

    不管怎样!

    假设您正在尝试获得恰好介于红色和黑色之间 50% 的颜色。

    所以你在插值 0xFF0000 和 0x000000。您会期望结果为 0x800000 或 0x7F0000,对吧?

    但这不是你得到的。相反,您会得到 0x7F8000,这是一种暗黄色。

    就个人而言,我会这样做:

    $rgbA = array(
        ($corA & 0xFF0000) >> 16,
        ($corA & 0x00FF00) >> 8,
        ($corA & 0x0000FF)
    );
    $rgbB = array(
        ($corB & 0xFF0000) >> 16,
        ($corB & 0x00FF00) >> 8,
        ($corB & 0x0000FF)
    );
    $rgbC = array_map(
        function($a,$b) use ($lerp) {return round($a+($b-$a)*$lerp);},
        $rgbA, $rgbB
    );
    // if you want a number:
    return $rgbC[0]<<16 | $rgbC[1]<<8 | $rgbC[2];
    // if you want an HTML hex code:
    return sprintf("#%02X%02X%02X",$rgbC[0],$rgbC[1],$rgbC[2]);
    

    【讨论】:

    • 为什么要更改所有代码?原来的那个是对的,添加一个简单的按位与操作和正确的掩码它是有效的。 array_map 是不必要的,位移也是!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多