Algorithm to find which two colors mix to form a third color (in JavaScript)

徘徊边缘 提交于 2019-12-23 21:27:04

问题


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)

  1. chose one color c1

    to be able to mix up to c0 the c1 must be less or equal to c0 on per channel bases. So for example random lesser color:

    r1 = Random(r0);
    g1 = Random(g0);
    b1 = Random(b0);
    
  2. 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)

  1. chose one color c1

    this time c1 must be c1>=c0 so again random such color example:

    r1 = r0 + Random(255-r0);
    g1 = g0 + Random(255-g0);
    b1 = b0 + Random(255-b0);
    
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!