Алгоритм, чтобы найти, какие два цвета смешиваются, чтобы сформировать третий цвет (в JavaScript) - PullRequest
3 голосов
/ 05 июня 2019

Я ищу библиотеку / алгоритм / технику, чтобы взять 3 аддитивных или вычитающих цвета и определить, какая комбинация из двух приводит к некоторому цвету x.

Это неправильный пример (поскольку я пока не очень разбираюсь в теории цвета), но это должно проиллюстрировать это.Скажем, у вас есть цвет, как зеленовато-коричневый #45512b.Проблема, которую нужно решить, - выяснить - для двух систем (аддитивной и вычитающей) - пару цветов, которые будут генерировать зеленовато-коричневый (заданный цвет).

Таким образом, у вас есть значение "зеленовато-коричневый"#45512b и хотите узнать, какие краски смешиваются, образуя этот цвет.Возможно, это #fff123 и #bbb456, которые субтрактивно объединяются в зеленовато-коричневый (просто придумывая).Затем для аддитивного смешивания вычислим два оттенка света из трех основных цветов света, используемых в вычислительных моделях, которые объединяются в зеленовато-коричневый.

В основном просто ищем это:

function additiveComponents(color) {
  return [ a, b ]
}

function subtractiveComponents(color) {
  return [ a, b ]
}

Цвет ввода не обязательно должен быть в шестнадцатеричном формате, любое из цветовых пространств будет работать.Но в конце я хотел бы преобразовать два выходных значения обратно в шестнадцатеричное значение.

Один наивный способ, который я мог бы себе представить, это использовать алгоритм обратного действия (алгоритм для смешивания двухцвета в третий цвет), и попробуйте каждую комбинацию цветов, пока не найдете правильный.Но это было бы супер неэффективно, задаваясь вопросом, есть ли лучший способ или стандартная техника.

1 Ответ

1 голос
/ 05 июня 2019

использование Цветовая модель RGB . Я предполагаю, что вы получили 8 бит на цвет канала c0=(r0,g0,b0) и хотите знать c1,c2, что микшируется обратно в c0.

Аддитивное смешивание (источники света)

  1. выбрал один цвет c1

    , чтобы иметь возможность смешивать до c0, c1 должен быть меньше или равен c0 на основе канала. Так, например, случайный меньший цвет:

    r1 = Random(r0);
    g1 = Random(g0);
    b1 = Random(b0);
    
  2. вычислить отсутствующий цвет c2

    просто используйте аддитивную логику:

    c0 = c1 + c2
    

    так

    c2 = c0 - c1
    
    r2 = r0 - r1
    g2 = g0 - g1
    b2 = b0 - b1
    

Субструктивное смешивание (фильтры, краски)

  1. выбрал один цвет c1

    на этот раз c1 должно быть c1>=c0 поэтому снова случайный пример такого цвета:

    r1 = r0 + Random(255-r0);
    g1 = g0 + Random(255-g0);
    b1 = b0 + Random(255-b0);
    
  2. вычислить отсутствующий цвет c2

    просто используйте субстративную логику:

    c0 = c1 - c2
    

    так

    c2 = c1 - c0
    
    r2 = r1 - r0
    g2 = g1 - g0
    b2 = b1 - b0
    

[Edit1] пример

Я только что закодировал простое приложение на C ++ / VCL, чтобы проверить это. Таким образом, я получил 3 полосы прокрутки, чтобы выбрать RGB целевого цвета c0, а затем несколько панелей, чтобы показать c1,c2 и их сочетание, чтобы визуально проверить его работу как следует. Вот код:

//$$---- 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;
    }
//---------------------------------------------------------------------------

А вот и скриншот:

screenshot

Единственным важным элементом в коде является событие sb_rgbChange, которое вызывается при любом изменении любой из 3 полос прокрутки. Он вычисляет цвета c1,c2 как для аддитивной, так и для субстративной логики и выводит цвета в панели.

Это работает без каких-либо проблем ... Кстати, вы правы, даже мой Random(x) генерирует x, поэтому ограничение должно быть 255 (я уже исправил ответ).

Здесь полный исходный код ( BDS2006 C ++ / VCL / Win32 ) и двоичный файл Win32:

...