2012-05-11 121 views
5

是否可以根據定義的「中心值」檢查某個十六進制顏色是更接近FFF還是000?計算色差

我想根據#888檢查顏色是否接近#FFF或#000。 因此,如果我檢查#EFEFEF它應該返回#FFF,如果我嘗試#878787它應該返回#000。

這是如何實現的?我不知道該怎麼尋找在谷歌...

在此先感謝

+1

不是#898989高於#888(#888888),因此應該返回#fff? #878787應該是在我看來返回#000的highes值... – oezi

+0

您需要決定如何計算[距離](http://en.wikipedia.org/wiki/Color_difference)。 – Jon

+1

@oezi:他希望使用#888作爲偏好參考顏色,這意味着他真正想要做的是比較#888和#FFF之間的顏色,並根據哪個更接近(基本上)返回#000或#FFF如果顏色比#888更接近#FFF,則返回#000)。 –

回答

2

解決問題的最簡單方法是使用灰度值計算顏色之間的距離(還有其他方法,但這很簡單)。因此,像:

// returns a distance between two colors by comparing each component 
// using average of the RGB components, eg. a grayscale value 
function color_distance($a, $b) 
{ 
    $decA = hexdec(substr($a, 1)); 
    $decB = hexdec(substr($a, 1)); 
    $avgA = (($decA & 0xFF) + (($decA >> 8) & 0xFF) + (($decA >> 16) & 0xFF))/3; 
    $avgB = (($decB & 0xFF) + (($decB >> 8) & 0xFF) + (($decB >> 16) & 0xFF))/3; 
    return abs($avgA - $avgB); 
} 

// I am going to leave the naming of the function to you ;) 
// How this works is that it'll return $minColor if $color is closer to $refColorMin 
// and $maxColor if $color is closer to $refColorMax 
// all colors should be passed in format #RRGGBB 
function foo($color, $refColorMin, $refColorMax, $minColor, $maxColor) 
{ 
    $distMin = color_distance($color, $refColorMin); 
    $distMax = color_distance($color, $refColorMax); 
    return ($distMin < $distMax) ? $minColor : $maxColor; 
} 

// Example usage to answer your original question: 
$colorA = foo('#EFEFEF', '#888888', '#FFFFFF', '#000000', '#FFFFFF'); 
$colorA = foo('#898989', '#888888', '#FFFFFF', '#000000', '#FFFFFF'); 
// Check the values 
var_dump($colorA, $colorB); 

輸出是:

string(7) "#FFFFFF" 
string(7) "#000000" 
3

您可以將顏色轉換爲數字:

$color_num = hexdec(substr($color, 1)); // skip the initial # 

然後比較他們要麼0x00xffffff

你也可以把它們分解成R,G和B三種比較;然後平均他們?不知道你是如何精確想要這件事物:)

+0

直接比較轉換後的十進制值不是一個好主意,因爲某些組件存儲的位的值比其他組件的值高。例如,如果紅色比特存儲在最高比特位中,藍色比特存儲在最低比特比特中,則紅色比特將總體上比藍色和綠色比特更重,這根本不會給出非常準確的結果。你使用平均數的想法是好的;這也是我在答案中使用的。 –

+0

@reko_t好點:)你的答案比我的嘿嘿 –

1

你可以做類似如下:

function hex2rgb($hex) { 
    $hex = str_replace("#", "", $hex); 

    if(strlen($hex) == 3) { 
     $r = hexdec(substr($hex,0,1).substr($hex,0,1)); 
     $g = hexdec(substr($hex,1,1).substr($hex,1,1)); 
     $b = hexdec(substr($hex,2,1).substr($hex,2,1)); 
    } else { 
     $r = hexdec(substr($hex,0,2)); 
     $g = hexdec(substr($hex,2,2)); 
     $b = hexdec(substr($hex,4,2)); 
    } 
    $rgb = array($r, $g, $b); 
    //return implode(",", $rgb); // returns the rgb values separated by commas 
    return $rgb; // returns an array with the rgb values 
} 

$rgb = hex2rgb("#cc0"); 

從,你可以採取$ RGB值,看看它們的值,平均面積更大高於或低於122.5。如果它大於122.5,你會接近#FFFFFF,低於122.5,你會接近#000000。

0

謝謝大家的幫助!

在我的startpost中,我提出了oezi提到的一個小錯字。對我來說,解決方案是一個小的修改,以接受的答案(由reko_t):

function color_distance($sColor1, $sColor2) 
{ 
    $decA = hexdec(substr($sColor1, 1)); 
    $decB = hexdec(substr($sColor2, 1)); 
    $avgA = (($decA & 0xFF) + (($decA >> 8) & 0xFF) + (($decA >> 16) & 0xFF))/3; 
    $avgB = (($decB & 0xFF) + (($decB >> 8) & 0xFF) + (($decB >> 16) & 0xFF))/3; 
    return abs($avgA - $avgB); 
} 

function determine_color($sInputColor, $sRefColor, $sMinColor, $sMaxColor) 
{ 
    $distRef = color_distance($sInputColor, $sRefColor); 
    $distMin = color_distance($sInputColor, $sMinColor); 
    $distMax = color_distance($sInputColor, $sMaxColor); 

    return $distMax - $distRef < $distMin - $distRef ? $sMinColor : $sMaxColor; 
} 

我不需要此功能,以確定哪些可以通過一些設置來設置背景色文本顏色。謝謝! :)學分reko_t!