Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate colordifference

Tags:

php

Is it possible to check if a certain hexadecimal color is closer to FFF or 000 based on a defined 'center-value'?

I want to check if a color lies closer to #FFF or #000 based on #888. So if I check for #EFEFEF it should return #FFF and if I try #878787 it should return #000.

How can this be achieved? I'm not sure what to search for on Google...

Thanks in advance

like image 948
Ben Fransen Avatar asked May 11 '12 12:05

Ben Fransen


2 Answers

The easiest way to solve your problem is to calculate the distance between colors using their greyscale values (there are other ways, but this is simple). So something like:

// 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);

The output is:

string(7) "#FFFFFF"
string(7) "#000000"
like image 30
reko_t Avatar answered Sep 19 '22 06:09

reko_t


You could convert the colours to numbers:

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

Then compare them to either 0x0 or 0xffffff.

You could also break them down into R, G and B and make three comparisons; then average them? Not sure how precise you want this thing :)

like image 188
Ja͢ck Avatar answered Sep 20 '22 06:09

Ja͢ck