问题
I am looking for a library/algorithm/technique to take the 3 additive or subtractive colors and determine what combination of two results in some color x
.
This is not a correct example (as I don't know much about color theory yet), but this is to illustrate the point. Say you have a color like greenish brown #45512b
. The problem to solve is figure out -- for the two systems (additive and subtractive) -- the pair of colors that will generate greenish brown (the given color).
So you have the value "greenish brown" #45512b
, and want to know what paints mix together to form this color. Maybe it is #fff123
and #bbb456
that combine subtractively to form greenish brown (just making this up). Then for additive mixing, figuring out the two shades of light of the 3 base colors of light used in computational models that combine to form greenish brown.
Basically just looking for this:
function additiveComponents(color) {
return [ a, b ]
}
function subtractiveComponents(color) {
return [ a, b ]
}
The input color doesn't need to be in hex format, any of the color spaces would work. But in the end I would like to convert the two output values back to a hex value.
One naive way I could imagine doing this is to take the reverse algorithm (algorithm to mix two colors into a third color), and try every combination of colors until you find the right one. But that would be super inefficient, wondering if there is a better way or standard technique.
回答1:
use RGB color model. I am assuming you got 8 bit per channel color c0=(r0,g0,b0)
and want to know c1,c2
that mix back to c0
.
Additive mixing (light sources)
chose one color
c1
to be able to mix up to
c0
thec1
must be less or equal toc0
on per channel bases. So for example random lesser color:r1 = Random(r0); g1 = Random(g0); b1 = Random(b0);
compute the missing color
c2
simply use the additive logic:
c0 = c1 + c2
so
c2 = c0 - c1 r2 = r0 - r1 g2 = g0 - g1 b2 = b0 - b1
Substractive mixing (filters, paint colors)
chose one color
c1
this time
c1
must bec1>=c0
so again random such color example:r1 = r0 + Random(255-r0); g1 = g0 + Random(255-g0); b1 = b0 + Random(255-b0);
compute the missing color
c2
simply use the substractive logic:
c0 = c1 - c2
so
c2 = c1 - c0 r2 = r1 - r0 g2 = g1 - g0 b2 = b1 - b0
[Edit1] example
I just encoded a simple C++/VCL app to test this. So I got 3 sscrollbars to chose RGB of target color c0
and then some panels to show the c1,c2
and their mix to visually verify its working as should. Here the code:
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "win_main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
const int _r=0; // channel order
const int _g=1;
const int _b=2;
const int _a=3;
union color
{
BYTE db[4]; // channel access
DWORD dd; // all 32 bit of color
TColor c; // VCL/GDI color (you can ignore this)
};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
sb_rgbChange(this);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sb_rgbChange(TObject *Sender)
{
int i;
color c0,c1,c2,c;
Randomize();
// get c0 color from R,G,B sliders
c0.db[_r]=255-sb_r->Position;
c0.db[_g]=255-sb_g->Position;
c0.db[_b]=255-sb_b->Position;
c0.db[_a]=0;
pan_c0->Color=c0.c; // just show color on some panel
// additive
for (i=0;i<3;i++) c1.db[i]=Random(c0.db[i]); c1.db[_a]=0; // generate c1 <= c0
for (i=0;i<3;i++) c2.db[i]=c0.db[i]-c1.db[i]; c2.db[_a]=0; // compute c2 = c0 - c1
for (i=0;i<3;i++) c.db[i]=c1.db[i]+c2.db[i]; c.db[_a]=0; // verify c = c1 + c2
pan_add_c1->Color=c1.c; // just show colors on some panels
pan_add_c2->Color=c2.c;
pan_add_c ->Color= c.c;
// substractive
for (i=0;i<3;i++) c1.db[i]=c0.db[i]+Random(255-c0.db[i]); c1.db[_a]=0; // generate c1 >= c0
for (i=0;i<3;i++) c2.db[i]=c1.db[i]-c0.db[i]; c2.db[_a]=0; // compute c2 = c1 - c0
for (i=0;i<3;i++) c.db[i]=c1.db[i]-c2.db[i]; c.db[_a]=0; // verify c = c1 - c2
pan_sub_c1->Color=c1.c; // just show colors on some panels
pan_sub_c2->Color=c2.c;
pan_sub_c ->Color= c.c;
}
//---------------------------------------------------------------------------
And here a screenshot:
The only important stuff in code is the sb_rgbChange
event which is called on any change of any of the 3 scrollbars. It compute the c1,c2
colors for both additive and substractive logic and output the colors into pannels.
It works without any problem... btw You where right even my Random(x)
generates x
so the limit should be 255 (I already repaired the answer).
Here complete source code (BDS2006 C++/VCL/Win32) and Win32 binary:
- Demo
来源:https://stackoverflow.com/questions/56454340/algorithm-to-find-which-two-colors-mix-to-form-a-third-color-in-javascript