Подтвердить что ты не робот

Как определить "светлые" цвета с помощью PHP

Я работаю над проектом динамического магазина и использую цикл, чтобы напечатать все варианты цвета для продукта в виде цветовых рамок, однако мне действительно нужно добавить "границу" для этих светлых цветов. Я пробовал что-то вроде следующего, но оно очень ограничено, на самом деле оно ограничено только белым цветом, оно не будет ловить что-то вроде #ddd, #eea... и т.д.

Вот мой цикл:

foreach($colors as $color) {
    $color = trim($color);
    if (!empty($color)) {
        if (in_array($color, array('white','White','#fff','#FFF','#FFFFFF','#ffffff'))) {
            $bordercolor = '#bbb';
        } else {
            $bordercolor = $color;
        }
    }
}

Цвета - это массив из бэкэнда, такой как: White, # 000, # cc0000 и т.д. Не имеет смысла добавлять все исключения также в условие if/else, какая-нибудь быстрая идея?

4b9b3361

Ответ 1

Преобразование цвета HTML в RGB, затем в Hue-Saturation-Lightnes (HSV)

<?php

function HTMLToRGB($htmlCode)
  {
    if($htmlCode[0] == '#')
      $htmlCode = substr($htmlCode, 1);

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

    $r = hexdec($htmlCode[0] . $htmlCode[1]);
    $g = hexdec($htmlCode[2] . $htmlCode[3]);
    $b = hexdec($htmlCode[4] . $htmlCode[5]);

    return $b + ($g << 0x8) + ($r << 0x10);
  }

function RGBToHSL($RGB) {
    $r = 0xFF & ($RGB >> 0x10);
    $g = 0xFF & ($RGB >> 0x8);
    $b = 0xFF & $RGB;

    $r = ((float)$r) / 255.0;
    $g = ((float)$g) / 255.0;
    $b = ((float)$b) / 255.0;

    $maxC = max($r, $g, $b);
    $minC = min($r, $g, $b);

    $l = ($maxC + $minC) / 2.0;

    if($maxC == $minC)
    {
      $s = 0;
      $h = 0;
    }
    else
    {
      if($l < .5)
      {
        $s = ($maxC - $minC) / ($maxC + $minC);
      }
      else
      {
        $s = ($maxC - $minC) / (2.0 - $maxC - $minC);
      }
      if($r == $maxC)
        $h = ($g - $b) / ($maxC - $minC);
      if($g == $maxC)
        $h = 2.0 + ($b - $r) / ($maxC - $minC);
      if($b == $maxC)
        $h = 4.0 + ($r - $g) / ($maxC - $minC);

      $h = $h / 6.0; 
    }

    $h = (int)round(255.0 * $h);
    $s = (int)round(255.0 * $s);
    $l = (int)round(255.0 * $l);

    return (object) Array('hue' => $h, 'saturation' => $s, 'lightness' => $l);
  }

$colour = '#F12346';
$rgb = HTMLToRGB($colour);
$hsl = RGBToHSL($rgb);

var_dump($hsl);

Использование:

$colour = '#F12346';
$rgb = HTMLToRGB($colour);
$hsl = RGBToHSL($rgb);
if($hsl->lightness > 200) {
  // this is light colour!
}

Источник:

Демо:

Ответ 2

Что бы я делал в этой ситуации, это обнаружить легкость цвета, используя HSL и сравнить это с определенным процентом. Например, атрибут lightness в алгоритме HSL принимает цветность (M - m, где M - наибольшее значение RGB, а m - наименьшее значение RGB) и делит это на 2.

function lightness($R = 255, $G = 255, $B = 255) {
    return (max($R, $G, $B) + min($R, $G, $B)) / 510.0; // HSL algorithm
}

Вышеуказанная функция вернет процент от того, насколько свет вы выбрали (для этого нужны простые преобразования hex → rgb, но это должно быть довольно легко). Причина, по которой я разделил 510 вместо 2, состоит в том, что для того, чтобы получить процент после деления на 2, вы разделите его на 255. Чтобы сделать это быстрее, вы можете просто сказать: (x / 2) / 255 = x / 510. Затем я сравнил значение, возвращаемое указанной функцией, например, на 80%.

$r = hexdec($hex[0].$hex[1]);
$g = hexdec($hex[2].$hex[3]);
$b = hexdec($hex[4].$hex[5]);

if(lightness($r, $g, $b) >= .8) {
    // add border
} else {
    // no border
}

Ответ 3

В дополнение к другим формулам, приведенным в других ответах, вы можете рассмотреть Luma.

function luma($r, $g, $b)
{
  return (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) / 255;
}

$l = luma(0, 15, 255);

Значения ближе к 0 будут более темными. Значения ближе к 1 будут легче.

Ответ 4

Короткий путь, если у вас есть цвет RGB в виде шестнадцатеричной строки:

$hexRGB = "4488BB";
if(hexdec(substr($hexRGB,0,2))+hexdec(substr($hexRGB,2,2))+hexdec(substr($hexRGB,4,2))> 382){
    //bright color
}else{
    //dark color
}

Ответ 5

Также существует более простой способ с еще меньшим количеством кода:

<?php
//Functions

function getRGB($colorCode) {
    //Turn html color code into RGB
    $var_R = substr($colorCode, 0, 2);
    $var_G = substr($colorCode, 2, 2);
    $var_B = substr($colorCode, 4, 2);  

    //Get Hex values
    $val_R = hexdec($var_R);
    $val_G = hexdec($var_G);
    $val_B = hexdec($var_B);

    //Red is seen as light too, gets fixed with this
    $remRed = hexdec('99');
    if ($val_R > $remRed) {
        $RGB = $val_G.' '.$val_B;
    } else {
        $RGB = $val_R.' '.$val_G.' '.$val_B;
    }

    return $RGB;
}

function getHSL($R = 255, $G = 255, $B = 255) {
    $hsl = (max($R, $G, $B) + min($R, $G, $B)) / 510.0;
    return $hsl;
}
?>

Теперь вызов:

$color = 0000FF; //Blue
$RGBcode = getRGB($color); //Returns 0 0 255
$RGBcode = str_replace(' ', ', ', $RGBcode); //Replaces an empty space with a ,
$val_HSL = getHSL($RGBcode); //Returns value from 0.5 to 1
if ($val_HSL >= 0.8) {
    //Reject color
} else {
    //Accept Color
    $color = '#'.$color; //Sets it to html: #0000FF
}