2012-09-01 20 views
12

Estoy trabajando en un proyecto de tienda dinámica y utilizo un bucle para imprimir todas las opciones de color para un producto como cuadros de color, sin embargo, realmente necesito agregar un "borde" a estos colores que son luz He intentado algo como lo siguiente, pero es muy limitado, en realidad se limita al color blanco solamente, no va a coger algo así como #ddd, etc ... #eeaCómo detectar colores "claros" con PHP

Aquí es mi bucle:

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; 
        } 
       } 
    } 

Colors es una matriz de backend como: White, # 000, # cc0000, etc. No es práctico agregar todas las excepciones en la condición if/else también, ¿alguna idea rápida?

+7

Google para ' RGB A HSV (HSL) '- Valor de saturación de tono (luminosidad). Mayor valor de luminosidad es un color más claro. – Peter

+0

Esta pregunta podría ayudarlo: [RGB a HSV en PHP] (http://stackoverflow.com/q/1773698/112968). A continuación, puede comprobar simplemente los valores de V por encima de un cierto umbral. – knittl

+0

http://stackoverflow.com/questions/5614011/intelligent-color-detection verifique esto –

Respuesta

13

transformación de color HTML a RGB, entonces a 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); 

Uso:

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

Fuente:

Demostración:

+0

¿qué significa? – Scramble

+0

existe la posibilidad de optimizar esta elegante solución. es decir, # FFFC00 (amarillo brillante) no se detectará como un color claro por encima de 150 –

6

Lo que haría en esta situación es detectar la luminosidad del color usando HSL, y compararlo con un cierto porcentaje. Por ejemplo, el atributo de ligereza en el algoritmo de HSL toma el croma (M - m, donde M es el valor RGB más grande y m es el valor RGB más pequeño) y divide que por 2.

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

La función anterior volvería un porcentaje de qué tan claro es el color que ha seleccionado (también se requieren conversiones simples de hexadecimal -> rgb, pero eso debería ser bastante fácil). La razón por la que dividí por 510 en lugar de 2 es porque para obtener el porcentaje de después de dividiendo por 2, se divide por 255. Para hacerlo más rápido, simplemente puede decir: (x/2)/255 = x/510. Luego compararía el valor devuelto por la función anterior con, digamos, 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 
} 
+0

Gran solución. Solo quería señalar a los demás que el valor '$ hex' no debería tener el' # '; por ejemplo: '$ hex = 'aaaaaa';'; – Alvaro

+0

¡Gran solución de hecho! – ChristianG

4

Además de otras fórmulas dadas por otras respuestas, es posible que desee considerar Luma.

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

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

Los valores más cercanos a 0 serán más oscuros. Los valores más cercanos a 1 serán más claros.

0

también hay una manera más sencilla con menos código:

<?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; 
} 
?> 

Ahora el llamado:

$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 
} 
0

manera corta si tiene color RGB:

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