PHP根据唯一值生成RGB颜色到对象

时间:2018-06-27 17:30:04

标签: php algorithm function math colors

我知道之前已经有人问过这个问题,但是我需要比SO提供的其他答案更多的帮助。

我目前有一个foreach循环,该循环遍历数据库中的记录。每行包含一个唯一的“ id”主要属性(1、2、3、4、5等)。

在我的循环中,我需要根据其ID为每个记录生成一个UNIQUE RGB值。所得的RGB值将应用于绑定到该记录的HTML元素的文本。生成的颜色必须对记录本身是唯一的(通过“ id”),这就是为什么我不使用循环迭代器的原因。

我已经创建了一个工作函数来为我执行此操作,但是我还需要做一件事-我需要rgb值在白色背景上具有大于4:5:1的对比度。我具有的功能生成的颜色太亮,使文本难以阅读。如何修改我的功能以产生在白色背景上对比度很好的深色?

function makeRgbFromValue(int $value){
    $hash = md5($value);

    return implode(", ", [
        hexdec(substr($hash, 0, 2)), // r
        hexdec(substr($hash, 2, 2)), // g
        hexdec(substr($hash, 4, 2))  // b
    ]);
}

// Example output: "100, 201, 20"

// My html, using Laravel Blade syntax:

@foreach($categories as $cat)
    <a 
        href="/blog/channels/{{ $cat->slug }}"
        style="color: rgb(
           {{ makeRgbFromValue($cat->id) }}
        )"
    >
        {{ $cat->name }}
    </a>
@endforeach

也许这是不可能的...但是我希望其中一位数学天才能够帮助我:)

2 个答案:

答案 0 :(得分:0)

您可以计算亮度:

function lumdiff($R1,$G1,$B1,$R2,$G2,$B2){
    $L1 = 0.2126 * pow($R1/255, 2.2) +
          0.7152 * pow($G1/255, 2.2) +
          0.0722 * pow($B1/255, 2.2);

    $L2 = 0.2126 * pow($R2/255, 2.2) +
          0.7152 * pow($G2/255, 2.2) +
          0.0722 * pow($B2/255, 2.2);

    if($L1 > $L2){
        return ($L1+0.05) / ($L2+0.05);
    }else{
        return ($L2+0.05) / ($L1+0.05);
    }
}

为获得最佳可读性,返回值应大于5。 找到功能here

但是您应该从哈希中获取另一个字符以获取另一种颜色,因此发生碰撞的可能性更高。

function makeRgbFromValue($value){
    $hash = md5($value);
    $brightness = 0;
    $shift = 0;

    while($brightness < 5 && $shift<26) {
        $color = [
            hexdec(substr($hash, $shift, 2)), // r
            hexdec(substr($hash, $shift+2, 2)), // g
            hexdec(substr($hash, $shift+4, 2))  // b
        ];
        $brightness = lumdiff($color[0], $color[1], $color[2], 255,255,255);
        $shift++;
    }

    return implode(", ", $color);
}

我相信会在25个循环中找到一种颜色:)

答案 1 :(得分:0)

虽然很难翻译,但HSV可能是更好的色彩空间。我喜欢选择一个饱和度[0.75很好],然后使用“色相”和“值”。

this gist提升HSV / RGB转换功能:

function HSV_TO_RGB ($H, $S, $V) {
    $RGB = array(); 
    if($S == 0) { 
        $R = $G = $B = $V * 255; 
    } else { 
        $var_H = $H * 6; 
        $var_i = floor( $var_H ); 
        $var_1 = $V * ( 1 - $S ); 
        $var_2 = $V * ( 1 - $S * ( $var_H - $var_i ) ); 
        $var_3 = $V * ( 1 - $S * (1 - ( $var_H - $var_i ) ) ); 
        if       ($var_i == 0) { $var_R = $V     ; $var_G = $var_3  ; $var_B = $var_1 ; } 
        else if  ($var_i == 1) { $var_R = $var_2 ; $var_G = $V      ; $var_B = $var_1 ; } 
        else if  ($var_i == 2) { $var_R = $var_1 ; $var_G = $V      ; $var_B = $var_3 ; } 
        else if  ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2  ; $var_B = $V     ; } 
        else if  ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1  ; $var_B = $V     ; } 
        else                   { $var_R = $V     ; $var_G = $var_1  ; $var_B = $var_2 ; } 
        $R = $var_R * 255; 
        $G = $var_G * 255; 
        $B = $var_B * 255; 
    } 
    $RGB['R'] = $R; 
    $RGB['G'] = $G; 
    $RGB['B'] = $B; 
    return $RGB; 
}

然后:

$fmt = '<span style="background-color: #%s" title="%s">%s</span>' . "\n";
$fill = str_repeat('&nbsp;', 5);

$S = 0.75;
for($i=0; $i<25; $i++) {
    $hash = md5(mt_rand());
    $H =   hexdec(substr($hash, 0, 2))/255;
    $V = ( hexdec(substr($hash, 2, 2))/255 ) / 2 + 0.5; // pick from the brighter half
    $rgb = implode('', array_map(
    function($a){
        return str_pad(dechex(intval($a)), 2, '0', STR_PAD_LEFT);
    }, HSV_TO_RGB($H, $S, $V)));
    printf($fmt, $rgb, sprintf("HSV(%0.2f,%0.2f,%0.2f)", $H, $S, $V), $fill);
}

给我们类似的东西

yay colored boxes!