использование Цветовая модель RGB . Я предполагаю, что вы получили 8 бит на цвет канала c0=(r0,g0,b0)
и хотите знать c1,c2
, что микшируется обратно в c0
.
Аддитивное смешивание (источники света)
выбрал один цвет c1
, чтобы иметь возможность смешивать до c0
, c1
должен быть меньше или равен c0
на основе канала. Так, например, случайный меньший цвет:
r1 = Random(r0);
g1 = Random(g0);
b1 = Random(b0);
вычислить отсутствующий цвет c2
просто используйте аддитивную логику:
c0 = c1 + c2
так
c2 = c0 - c1
r2 = r0 - r1
g2 = g0 - g1
b2 = b0 - b1
Субструктивное смешивание (фильтры, краски)
выбрал один цвет c1
на этот раз c1
должно быть c1>=c0
поэтому снова случайный пример такого цвета:
r1 = r0 + Random(255-r0);
g1 = g0 + Random(255-g0);
b1 = b0 + Random(255-b0);
вычислить отсутствующий цвет 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;
}
//---------------------------------------------------------------------------
А вот и скриншот:
Единственным важным элементом в коде является событие sb_rgbChange
, которое вызывается при любом изменении любой из 3 полос прокрутки. Он вычисляет цвета c1,c2
как для аддитивной, так и для субстративной логики и выводит цвета в панели.
Это работает без каких-либо проблем ... Кстати, вы правы, даже мой Random(x)
генерирует x
, поэтому ограничение должно быть 255 (я уже исправил ответ).
Здесь полный исходный код ( BDS2006 C ++ / VCL / Win32 ) и двоичный файл Win32: