如何使用 PHP 生成更浅/更深的颜色?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3512311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:03:18  来源:igfitidea点击:

How to generate lighter/darker color with PHP?

phphtmlcsscolors

提问by eni

I have a hex value of some color, for example #202010.

例如,我有某种颜色的十六进制值#202010

How to generate a new color which is either lighter or darker given in percent (ie. 20% darker)in PHP?

如何在 PHP 中生成以百分比给出的更亮或更暗的新颜色 (即深 20%)

回答by Torkil Johnsen

Adjusting colour by percent, as in the example given by Frxstrem, is not ideal.

按百分比调整颜色,如 Frxstrem 给出的示例,并不理想。

If your colour is black (0,0,0 in RGB), you will be multiplying by zero, which will not yield any change at all. If your colour is dark gray (for instance 2,2,2 in RGB), you will have to lighten by 50% to just move up to (3,3,3). On the other hand, if you have an RGB colour of (100,100,100), the adjustment of 50% will move you up to (150,150,150), which is a much bigger change in comparison.

如果您的颜色是黑色(RGB 中的 0,0,0),您将乘以零,这根本不会产生任何变化。如果您的颜色是深灰色(例如 RGB 中的 2,2,2),则您必须将颜色调亮 50% 才能向上移动到 (3,3,3)。另一方面,如果您的 RGB 颜色为 (100,100,100),则 50% 的调整将使您上升到 (150,150,150),相比之下,这是一个更大的变化。

A much better solution would be to adjust by step/number (0-255) instead of by percent, for instance like this (PHP code):

更好的解决方案是按步骤/数字(0-255)而不是按百分比进行调整,例如像这样(PHP代码):

Edit 2014-01-06: Cleaned up the code a bit.

编辑 2014-01-06:稍微清理代码。

function adjustBrightness($hex, $steps) {
    // Steps should be between -255 and 255. Negative = darker, positive = lighter
    $steps = max(-255, min(255, $steps));

    // Normalize into a six character long hex string
    $hex = str_replace('#', '', $hex);
    if (strlen($hex) == 3) {
        $hex = str_repeat(substr($hex,0,1), 2).str_repeat(substr($hex,1,1), 2).str_repeat(substr($hex,2,1), 2);
    }

    // Split into three parts: R, G and B
    $color_parts = str_split($hex, 2);
    $return = '#';

    foreach ($color_parts as $color) {
        $color   = hexdec($color); // Convert to decimal
        $color   = max(0,min(255,$color + $steps)); // Adjust color
        $return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
    }

    return $return;
}

回答by Rod

The answers are wrong.

答案是错误的。

Using RGB model is a conceptual error.

使用 RGB 模型是一个概念错误。

You need to transform the color from RGB (or Hex form) into HSL.

您需要将颜色从 RGB(或十六进制形式)转换为 HSL。

That is Hue, Saturation, Lightness.

即色相、饱和度、明度。

Once you convert it from RGB into HSL, to lighten up the color you simply adjust the L value (lightness) by 10%. Then once you are done you convert back from HSL to RGB and you are done.

将其从 RGB 转换为 HSL 后,要使颜色变亮,只需将 L 值(亮度)调整 10%。然后一旦你完成,你就从 HSL 转换回 RGB,你就完成了。

Voila!

瞧!

RGB to HSV in PHP

PHP 中的 RGB 到 HSV

回答by Frxstrem

Here's an example:

下面是一个例子:

<?php
$color = '#aabbcc'; // The color we'll use

Extract the colors. I'd prefer to use regular expressions, though there are probably other more efficient ways too.

提取颜色。我更喜欢使用正则表达式,尽管可能还有其他更有效的方法。

if(!preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i', $color, $parts))
  die("Not a value color");

Now we have red in $parts[1], green in $parts[2]and blue in $parts[3]. Now, let's convert them from hexadecimal to integers:

现在我们有红色输入$parts[1],绿色输入$parts[2]和蓝色输入$parts[3]。现在,让我们将它们从十六进制转换为整数:

$out = ""; // Prepare to fill with the results
for($i = 1; $i <= 3; $i++) {
  $parts[$i] = hexdec($parts[$i]);

Then we'll decrease them by 20 %:

然后我们将它们减少 20%:

  $parts[$i] = round($parts[$i] * 80/100); // 80/100 = 80%, i.e. 20% darker
  // Increase or decrease it to fit your needs

Now, we'll turn them back into hexadecimal and add them to our output string

现在,我们将把它们转回十六进制并将它们添加到我们的输出字符串中

  $out .= str_pad(dechex($parts[$i]), 2, '0', STR_PAD_LEFT);
}

Then just add a "#" to the beginning of the string, and that's it!

然后只需在字符串的开头添加一个“#”,就可以了!

回答by maliayas

Torkil Johnsen's answer is based on fixed step which doesn't manipulate only brightness but also slightly changes the hue. Frxstrem's method has flaws too as Torkil Johnsen noted.

Torkil Johnsen 的答案基于固定步骤,它不仅操纵亮度,而且略微改变色调。正如 Torkil Johnsen 所指出的,Frxstrem 的方法也有缺陷。

I've taken this approach from a Github commentand improved the code. It works perfectly for any case.

我从Github 评论中采用了这种方法并改进了代码。它适用于任何情况。

/**
 * Increases or decreases the brightness of a color by a percentage of the current brightness.
 *
 * @param   string  $hexCode        Supported formats: `#FFF`, `#FFFFFF`, `FFF`, `FFFFFF`
 * @param   float   $adjustPercent  A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
 *
 * @return  string
 */
function adjustBrightness($hexCode, $adjustPercent) {
    $hexCode = ltrim($hexCode, '#');

    if (strlen($hexCode) == 3) {
        $hexCode = $hexCode[0] . $hexCode[0] . $hexCode[1] . $hexCode[1] . $hexCode[2] . $hexCode[2];
    }

    $hexCode = array_map('hexdec', str_split($hexCode, 2));

    foreach ($hexCode as & $color) {
        $adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
        $adjustAmount = ceil($adjustableLimit * $adjustPercent);

        $color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
    }

    return '#' . implode($hexCode);
}

Here is an example result:

这是一个示例结果:

example

例子

回答by pgee70

I was interested in this, but my question was how do I add a opacityto a colour?

我对此很感兴趣,但我的问题是如何为颜色添加不透明度

I wanted a colour to fade, not made lighter. i found this: http://www.gidnetwork.com/b-135.htmland it worked great- code posted from original site for SO readers.

我想要一种褪色的颜色,而不是变浅。我发现了这个:http: //www.gidnetwork.com/b-135.html并且它工作得很好 - 从原始站点为 SO 读者发布的代码。

function color_blend_by_opacity( $foreground, $opacity, $background=null )
{
    static $colors_rgb=array(); // stores colour values already passed through the hexdec() functions below.
    $foreground = str_replace('#','',$foreground);
    if( is_null($background) )
        $background = 'FFFFFF'; // default background.

    $pattern = '~^[a-f0-9]{6,6}$~i'; // accept only valid hexadecimal colour values.
    if( !@preg_match($pattern, $foreground)  or  !@preg_match($pattern, $background) )
    {
        trigger_error( "Invalid hexadecimal colour value(s) found", E_USER_WARNING );
        return false;
    }

    $opacity = intval( $opacity ); // validate opacity data/number.
    if( $opacity>100  || $opacity<0 )
    {
        trigger_error( "Opacity percentage error, valid numbers are between 0 - 100", E_USER_WARNING );
        return false;
    }

    if( $opacity==100 )    // $transparency == 0
        return strtoupper( $foreground );
    if( $opacity==0 )    // $transparency == 100
        return strtoupper( $background );
    // calculate $transparency value.
    $transparency = 100-$opacity;

    if( !isset($colors_rgb[$foreground]) )
    { // do this only ONCE per script, for each unique colour.
        $f = array(  'r'=>hexdec($foreground[0].$foreground[1]),
                     'g'=>hexdec($foreground[2].$foreground[3]),
                     'b'=>hexdec($foreground[4].$foreground[5])    );
        $colors_rgb[$foreground] = $f;
    }
    else
    { // if this function is used 100 times in a script, this block is run 99 times.  Efficient.
        $f = $colors_rgb[$foreground];
    }

    if( !isset($colors_rgb[$background]) )
    { // do this only ONCE per script, for each unique colour.
        $b = array(  'r'=>hexdec($background[0].$background[1]),
                     'g'=>hexdec($background[2].$background[3]),
                     'b'=>hexdec($background[4].$background[5])    );
        $colors_rgb[$background] = $b;
    }
    else
    { // if this FUNCTION is used 100 times in a SCRIPT, this block will run 99 times.  Efficient.
        $b = $colors_rgb[$background];
    }

    $add = array(    'r'=>( $b['r']-$f['r'] ) / 100,
                     'g'=>( $b['g']-$f['g'] ) / 100,
                     'b'=>( $b['b']-$f['b'] ) / 100    );

    $f['r'] += intval( $add['r'] * $transparency );
    $f['g'] += intval( $add['g'] * $transparency );
    $f['b'] += intval( $add['b'] * $transparency );

    return sprintf( '%02X%02X%02X', $f['r'], $f['g'], $f['b'] );
}

回答by Slawa

https://github.com/mikeemoo/ColorJizz-PHPallows to convert to HSL, change lightness component and convert back to RGB.

https://github.com/mikeemoo/ColorJizz-PHP允许转换为 HSL,更改亮度组件并转换回 RGB。

回答by phoenix

If you want a simple implementation and you don't care that much about the values being specifically above 50% lightness (or whatever your threshold), you can use my solution for lighter colors:

如果您想要一个简单的实现,并且您不太关心具体高于 50% 亮度(或任何您的阈值)的值,您可以使用我的解决方案来处理较浅的颜色:

$color = sprintf('#%06X', mt_rand(0xFFFFFF / 1.5, 0xFFFFFF));

The idea is to generate a random color in the higher part of the palette. You can adjust the results to be more or less dark by changing the "1.5" value:

这个想法是在调色板的较高部分生成随机颜色。您可以通过更改“1.5”值来调整结果或多或少暗:

  • larger will expand the palette into darker colors
  • smaller will curb it to lighter colors
  • 更大的将调色板扩展为更深的颜色
  • 较小的将抑制它为较浅的颜色

You can do the same for darker colors by setting the starting point of the random function to "0x000000" and dividing the end limit:

您可以通过将随机函数的起点设置为“0x000000”并除以结束限制来对较深的颜色执行相同的操作:

$color = sprintf('#%06X', mt_rand(0x000000, 0xFFFFFF / 1.5));

I know this is not a precise but it works for me.

我知道这不是一个精确的但它对我有用。