Calculate colordifference

Is it possible to check if any hexadecimal color is closer to FFF or 000 based on a certain "central value"?

I want to check if the color is closer to #FFF or # 000 based on # 888. Therefore, if I check #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 on google ...

Thanks in advance

+5
source share
4 answers

The easiest way to solve your problem is to calculate the distance between the colors using their grayscale values ​​(there are other ways, but it's easy). 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);

Conclusion:

string(7) "#FFFFFF"
string(7) "#000000"
+2
source

You can convert colors to numbers:

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

0x0 0xffffff.

R, G B ; ? , :)

+3

You can do something like the following:

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

From this, you can take the values ​​of $ rgb and see if their values ​​are on average an area greater or less than 122.5. If it is more than 122.5, you will be closer to #FFFFFF, below 122.5, you will be closer to # 000000.

+1
source

Thank you all for your help!

In my starter, I made a small typo, as mentioned by oesy. For me, the solution was a small modification of the accepted answer (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;
}

I need this function to determine the color of the text on the background color, which can be set using some settings. Thank you! :) Credits to reko_t!

0
source

All Articles