Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if color is in range [duplicate]

Tags:

php

Possible Duplicate:
“Distance” between colours in PHP

I want to detect if a RGB value is a certain shade of pink. I am unsure of how to proceed with this since there doesn't seem to be a range of RGB or hex values that follow a linear order for pink (one shade of pink is 255, 182, 193; #FFB6C1, while another is 238, 162, 173; #EEA2AD). Do you have any idea of what to do, assuming I know the beginning and ending RGB/hex values of my range?

like image 370
Jack Humphries Avatar asked Nov 23 '12 01:11

Jack Humphries


1 Answers

It looks fairly linear to me. However, you need to understand a bit of color theory.

I hope you don't mind me including a simple refresher of color theory here before answering your question. But it helps in understanding or formulating any solution.

First, I'm sure most will remember the color wheel they learned in kindergarten:

                                          Red
       Red                        Orange   |   Purple
        |                                \_|_/
       _o_        ---------->             _o_
      /   \                              / | \
  Yellow   Blue                   Yellow   |   Blue
                                         Green

Well, we need to modify it a bit. Because it turns out that Red and Blue are not really primary colors since you can get red by mixing Magenta with Yellow and you can get Blue by mixing Cyan with a bit of Red. So The modified color wheel uses printing colors: CMY:

        Magenta
     Red   |   Blue
         \_|_/
          _o_
         / | \
  Yellow   |   Cyan
         Green

This is basically the HSV color space (with S usually plotted going from the center to the edge of the wheel and V not plotted at all but usually can be changed by a slider). It is derived from printing colors CMY. So how can this help us with screen colors RGB?

Well, if you look carefully at it you'll notice that it is actually a composite of both printing and screen color space. It actually depicts the relationship between CMY and RGB:

        Magenta                 Magenta
     Red   |   Blue                |           Red     Blue
         \_|_/                     |              \_ _/
          _o_            ==       _o_       +       o
         / | \                   /   \              |
  Yellow   |   Cyan         Yellow    Cyan          |
         Green                                    Green

So, any RGB color can be understood by understanding this color wheel. For example, there is no Yellow in RGB. But notice that Yellow is the opposite of Blue. So, to get Yellow you subtract blue from a color:

rgb(100,80,10)  is a "yellowish" version of rgb(100,80,120)
            ^                                           ^

Once you understand this color wheel working with RGB values makes more sense. With enough practice you can compose and edit colors directly in #rrggbb syntax without consulting a color chart.

So, to answer your question. Say your target shade of pink is:

rgb(255,182,193)

We know two things about the color "pink":

  1. We percieve it as a kind of Red. So it makes sense that the target color has high Red value (in fact it is maximum).

  2. We percieve it as a very light Red. So it makes sense that the non-Red components are also quite high (both above 150).

So, to get shades close to your target color we need:

  1. R value significantly higher than G or B.
  2. All values to be quite high (above 150 or so).

By this definition we can identify pink as:

// Pseudo code:

is_pink (R,G,B) {
    return R > 200 &&  // make sure R is high
           G > 150 &&  // make sure G & B are relatively high
           B > 150 &&
           R > G &&    // make sure G & B are not higher than R
           R > B;
}

We can add another condition to reject "pink" that is slightly bluish or greenish by making sure that G & B are fairly similar:

// Pseudo code:

is_pink (R,G,B) {
    return R > 200 &&
           G > 150 &&
           B > 150 &&
           R > G &&
           R > B &&
           abs(G-B) < 20; // make sure it's neither bluish or greenish
}

You can tweak the values 200, 150 and 20 to suit your taste of pinkishness but you'll see that if we apply the above function to both your test colors (255,182,193) and (238,162,173) they'll both be identified as "pink".

like image 168
slebetman Avatar answered Oct 07 '22 01:10

slebetman