Viewed   84 times

I'm looking for a function that can accurately represent the distance between two colours as a number or something.

For example I am looking to have an array of HEX values or RGB arrays and I want to find the most similar colour in the array for a given colour

eg. I pass a function a RGB value and the 'closest' colour in the array is returned

 Answers

1

Each color is represented as a tuple in the HEX code. To determine close matches you need to subtract each RGB component separately.

Example:

Color 1: #112233 
Color 2: #122334
Color 3: #000000

Difference between color1 and color2: R=1,  G=1   B=1  = 0x3 
Difference between color3 and color1: R=11, G=22, B=33 = 0x66

So color 1 and color 2 are closer than
1 and 3.

edit

So you want the closest named color? Create an array with the hex values of each color, iterate it and return the name. Something like this;

function getColor($rgb)
{
    // these are not the actual rgb values
    $colors = array(BLUE =>0xFFEEBB, RED => 0x103ABD, GREEN => 0x123456);

    $largestDiff = 0;
    $closestColor = "";
    foreach ($colors as $name => $rgbColor)
    {
        if (colorDiff($rgbColor,$rgb) > $largestDiff)
        {
            $largestDiff = colorDiff($rgbColor,$rgb);
            $closestColor = $name;
        }

    }
    return $closestColor;

}

function colorDiff($rgb1,$rgb2)
{
    // do the math on each tuple
    // could use bitwise operates more efficiently but just do strings for now.
    $red1   = hexdec(substr($rgb1,0,2));
    $green1 = hexdec(substr($rgb1,2,2));
    $blue1  = hexdec(substr($rgb1,4,2));

    $red2   = hexdec(substr($rgb2,0,2));
    $green2 = hexdec(substr($rgb2,2,2));
    $blue2  = hexdec(substr($rgb2,4,2));

    return abs($red1 - $red2) + abs($green1 - $green2) + abs($blue1 - $blue2) ;

}
Thursday, December 1, 2022
2

In the end, despite the wonderful suggestions surrounding imagemagick I found a good solution using straight php. I was able to calculate the closest color through the use of delta E 2000 with a modified version of php-color-difference library found on github, here is my fork: https://github.com/nalipaz/php-color-difference

The pertinent example is:

<?php
include('lib/color_difference.class.php');

$palette = array(
  '00' => array(255, 255, 255),
  '01' => array(0, 0, 0),
  '02' => array(0, 0, 139),
  '03' => array(0, 128, 0),
  '04' => array(255, 0, 0),
  '05' => array(139, 0, 0),
  '06' => array(128, 0, 128),
  '07' => array(255, 165, 0),
  '08' => array(255, 255, 0),
  '09' => array(50, 205, 50),
  '10' => array(0, 128, 128),
  '11' => array(173, 216, 230),
  '12' => array(0, 0, 255),
  '13' => array(255, 105, 180),
  '14' => array(128, 128, 128),
  '15' => array(211, 211, 211),
);

$color_rgb = array(255, 255, 128);
$color_delta_e = new color_difference($color_rgb);
$match_index = $color_delta_e->getClosestMatch($palette);
$color = $palette[$match_index];

I am pretty happy with this solution and smaller amount of overhead. Thanks for the suggestions guys.

Wednesday, October 12, 2022
1

Use preg_replace_callback:

function mycallback($matches) {
    $bindings = array(
       0=>'white',
       1=>'black',
       2=>'blue',
       3=>'green',
       4=>'red',
       5=>'brown',
       6=>'purple',
    );

    $fg = isset($bindings[$matches[1]]) ? $bindings[$matches[1]] : 'transparent';
    $bg = isset($bindings[$matches[2]]) ? $bindings[$matches[2]] : 'transparent';

    return '<span style="color: '.$fg.'; background: '.$bg.';">'.$matches[3].'</span>';
}

$str = '^C3,1Hello^C foo ^C6,2World^C';
$str = preg_replace_callback('/^C([0-9]{1,2}),?([0-9]{1,2})(.*?)^C/', 'mycallback', $str);

echo $str;
Sunday, October 23, 2022
4

I once set up a hexagonal coordinate system in a game so that the y-axis was at a 60-degree angle to the x-axis. This avoids the odd-even row distinction.


(source: althenia.net)

The distance in this coordinate system is:

dx = x1 - x0
dy = y1 - y0

if sign(dx) == sign(dy)
    abs(dx + dy)
else
    max(abs(dx), abs(dy))

You can convert (x', y) from your coordinate system to (x, y) in this one using:

x = x' - floor(y/2)

So dx becomes:

dx = x1' - x0' - floor(y1/2) + floor(y0/2)

Careful with rounding when implementing this using integer division. In C for int y floor(y/2) is (y%2 ? y-1 : y)/2.

Tuesday, September 6, 2022
 
ag_boss
 
3

You can iterate over the matrix and find the coordinates of all the 1's (x1, y1). Then for each position in the cell (x2, y2), for all (x1, y1) in your list, find the minimum |x2 - x1| + |y2 - y1| (the Manhattan distance since it's a grid).

Tuesday, November 15, 2022
 
zac-k
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :