16

I am trying to mix two source RGB vectors to create a third "resultant vector" that is an intuitive mix of the first two.

Ideally, I would be able to emulate "real paint mixing characteristics", but for simplicity, I am trying to find a method where the resultant looks intuitively like what you'd get from combining the two source rgb's.

minimally, these characteristics:
RED + BLACK = DARK RED
RED + WHITE = LIGHT RED

optimally, also with real paint characteristics:
RED + BLUE = PURPLE
RED + YELLOW = ORANGE
(etc)

--

I am currently doing this the "lazy way" by adding the two source RGB vectors/255, then normalizing (and multiplying by 255). So, using this: [Red = <1,0,0> * 255] + [Blue = <0,0,1> * 255] gives Magenta=<1,0,1>/sqrt(2) * 255, though the other colors are less intuitive or even visible... I need a better method! Please help :-)

yos
  • 223
  • 2
  • 3
  • 7
  • Seems pretty much identical to http://stackoverflow.com/questions/398224/how-to-mix-colors-naturally-with-c – Jason Orendorff Dec 12 '09 at 02:47
  • 2
    You probably don't want "real paint" characteristics, because real paint doesn't work as well as you think it does. I'll bet you think that yellow+blue=green, but that isn't true in any color space I know. – Mark Ransom Dec 12 '09 at 03:24
  • I'm a little late to the party, but here is an implementation which might work. http://stackoverflow.com/a/14840112/475329 – Ben Holland Feb 12 '13 at 19:23
  • Yellow plus blue does make green in the context of additive color, which is what mixing paint together is. Displays use subtractive color, and software tends to reflect that. – Carl Smith Mar 22 '19 at 03:02

5 Answers5

16

Is what you suggested the same as a weighted average?

Average R = w1*R1 + w2*R2 + w3*R3 + ... + wn*Rn

Average G = w1*G1 + w2*G2 + w3*G3 + ... + wn*Gn

Average B = w1*B1 + w2*B2 + w3*B3 + ... + wn*Bn

The w's are the weighting fractions and the sum of them is 1.

R1 is the red component of the first color to mix, for example.

So if you wanted to mix two colors evenly, it would be:

Average R = 0.5*R1 + 0.5*R2

Average G = 0.5*G1 + 0.5*G2

Average B = 0.5*B1 + 0.5*B2

As for mapping the resultant color to a named color ("dark red") maybe just do a lookup table and pick the closest one?

John
  • 15,990
  • 10
  • 70
  • 110
  • 1
    How do you determine the w's or the W matrix to be able to mix rgb (or cmyk) like paint? – yos Dec 12 '09 at 02:46
  • 2
    If you're mixing 2 colors, the W is 1/2 or 0.5, exactly as the answer suggests. – Mark Ransom Dec 12 '09 at 03:20
  • Just to be clear, if the weights are equal, you could just leave them, and divide the result by the number of colors mixed instead `((R1 + R2 + R3) / 3)`. When they are unequal, their sum should equal `1`. The point is to get a mean average. – Carl Smith Mar 22 '19 at 03:09
11

The problem is that you're trying to relate two different color theories. RGB is additive color theory (colored light is emitted from the source). In this case the more of the spectrum you add to the mix, the closer you get to white.

For "paint mixing" you need to emulate subtractive color theory which governs the way reflected colors are mixed. (i.e. reflected light such as paints, different surfaces etc.) Here's an overview.

The JavaScript on this page is a clue as to how you might proceed in converting RGB to CMYK.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • The question asks about paint mixing, but the examples all seem more related to RGB mixing. I find CMYK mixing to be very counter-intuitive. – Mark Ransom Dec 12 '09 at 04:24
  • i interpreted the question to be asking about mixing RGB (additive) but getting CMYK (subtractive) results. – Paul Sasik Dec 12 '09 at 13:29
2

Mixing RGB colors to simulate subtractive color mixture (i.e., paint-like mixture) can be done by transforming the RGB values to spectral reflectance curves, then doing the mixture there. This question is very similar to another, stackoverflow.com/questions/10254022/, where the solution is discussed in more detail.

Community
  • 1
  • 1
Scott Burns
  • 81
  • 1
  • 4
1

I think you should really define what is "+" in your color scheme.

Based on your requirements, I've translated them into estimated hex color codes, (rgb represention can be deduced easily).

RED     + BLACK   = DARK RED  
#ff0000 + #000000 = #800000
RED     + WHITE   = LIGHT RED
#ff0000 + #ffffff = #ff8080

optimally, also with real paint characteristics:
RED     + BLUE    = PURPLE
#ff0000 + #0000ff = #800080
RED     + YELLOW  = ORANGE
#ff0000 + #ffff00 = #ff8000

I do not see a definite pattern which you can work out some formulas to achieve that.

John's and Nils' methods probably will come close to the colors but probably not to the exact values. I suggest you give theirs a try.

EDIT:
Updated the wrong color codes. Well it does made a lot more sense now.

o.k.w
  • 25,490
  • 6
  • 66
  • 63
0

//you could code in manually to return.

    function returnColour(clrRed, clrBlack){
        var clrRed:"#ff0000";
        var clrBlack:"#000000";
        var clrDarkRed:"#800000";
        if ( this.currentColor !== clrRed ) {
          return;
               }
          elseif (clrRed + clrBlack){ 
                 return clrDarkRed;
          }
    }

//just a proof of concept on one rather goofy way. a mathematical method would be useful ! just haven't had the time to get around to that though thinking about it for some time.