уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Уверен, что каждому читателю блога приходилось много раз смешивать краски и что-то где-то рисовать. По крайней мере, все мы ходили на уроки рисования в школе. Смешивание различных цветов дает новые цвета, которые, в свою очередь можно снова смешивать и в пределе получить, скажем, чёрный цвет — когда все краски замешаны в одну непонятную массу. Но это все в, скажем так, реальном мире. А как дела обстоят с цветами в мире программ? Цель работы на сегодня — «научить» нашу программу смешивать краски в нужных пропорциях и получать тот цвет, который Вы бы получили, смешав настоящие краски, а не пиксели на мониторе.

Работая с цветами в Delphi (да и не только с Delphi), мы уже привыкли, что для работы с цветом у нас есть модель RGB (Red, Green, Blue) в который все цвета получаются путем смешивания трех основных. Самый простой алгоритм смешивания двух RGB-цветов в равных пропорциях — это:

var R,G,B:byte;
begin
  R:=(R1+R2) div 2;
  G:=(G1+G2) div 2;
  B:=(B1+B2) div 2;
end;

Просто, удобно, лаконично. А теперь вернемся к нашей задаче. Как показать художнику, с кисточкой в одной руке и палитрой в другой, какой цвет он получит, если возьмет и смешает в своей палитре две краски? Попробуйте сейчас, используя приведенный выше код сложить два цвета: синий (0, 0, 255) и желтый (255, 255, 0). Что получится? Получится некое подобие серого цвета. Что-то типа такого:

Blue+Yellow=?

Blue+Yellow=?

А теперь попробуйте сделать то же самое, НО по-старинке, без компьютера, без RGB и прочих технических штук — возьмите два карандаша/маркера и почиркайте ими на белом листе бумаги. Что получилось?

Должно получиться что-то типа такого:

Blue+Yellow=Green

Blue+Yellow=Green

Как так получилось? Магии никакой нет, приведенный выше код, если и дает ошибку в определении нового цвета, то явно не такую, чтобы вместо зеленого получился серый цвет. И тут мы вплотную приблизились к тому, чтобы рассмотреть теоретическую часть задачи. Скажу сразу — глубоко в физику процесса я лезть не буду (тем более, что глубоко я в теории цвета никогда не копался) — расскажу кратко и ровно столько, чтобы хватило для решения задачи.

Цветовые модели

Как я сказал выше, мы все привыкли и, если не прекрасно, то хотя бы в общих чертах, представляем, что представляет из себя RGB.

RGB — это аддитивная модель цветового пространства.

Аддитивное смешение цветов — метод синтеза цвета, основанный на сложении аддитивных цветов, то есть цветов непосредственно излучающих объектов.

Любой цвет на «излучающим объекте», например, мониторе получается путем сложения трех составляющих — красных, зеленых и синих точек. Сложили три основных цвета — получили черный, обнулили три составляющих цвета — получили чистый белый.

В RGB  можно получить огромное количество всяких разных цветов, поэтому RGB нашла широкое применение в современной технике. Круг, изображенный на первой картинке этой статьи и есть своеобразное представление цветового пространства RGB.

Кроме RGB существует и другая цветовая модель —RYB:

RYB — цветовая модель субтрактивного синтеза, основанная на составлении цвета из красного (Red), жёлтого (Yellow) и голубого (Blue). Эта сложившаяся исторически система предшествовала становлению современной науки о цвете. Она не вписывается в современные представления о пиках восприятия спектра видимого света в трехстимульной модели зрения, однако применяется для представления цвета в изобразительном искусстве.

Субтрактивный синтез цвета — получение цвета путём вычитания из белого света отдельных спектральных составляющих.

Смотрим на модель RYB и видим:

RYB

RYB

Синий + Желтый = Зеленый

Обратите внимание, что любой цвет в RYB определяется тремя числами в диапазоне от 0 до 1.

  • 1,0,0 — красный цвет
  • 0,1,0 — желтый
  • 0,0,1 — голубой

Вот та цветовая модель с которой нам сегодня предстоит научиться работать. Конечно, кроме этих двух, существует ещё ряд цветовых моделей, например, HSL, XYZ, L*a*b, CMYK (то же, кстати, субтрактивная модель, как и RYB) и т.д. Сейчас рассматривать мы их не будем, но, вполне возможно, что позже я покажу как эти модели можно использовать в Delphi. А пока обратимся к нашей модели RYB и прикинем как мы можем её использовать в Delphi.

Сложение цветов в RYB

Итак, теперь мы знаем, что из себя представляет модель RYB. Есть три основных цвета (Primary Colors) Red, Yellow и Blue. Согласно RYB эти цвета нельзя получить путем смешивания.

Смешивая в равных пропорциях два любых основных цвета мы получим так называемые secondary colors.

Смешивая 2 части primary color с 1 частью secondary color мы получим tertiary Colors.

В итоге primary, secondary и tertitary colors образуют так называемое цветовое колесо, которое можно представить, например, так:

Цветовое колесо RYB

Цветовое колесо RYB

Как смешиваются цвета в RYB? Очень просто. К примеру нам надо смешать две части красного цвета и одну часть желтого.

Запишем цвет в RYB как:

type
 TRYBColor = record
   R: single;
   Y: single;
   B: single;
 end;
[...]
var Color1, Color2: TRYBColor;

а количество (или вес) в общей массе как

weight1, weight2: single

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

var NewRYB: TRYBColor;
    K: single;
begin
  NewRYB.R:=Color1.R*Weight1+Color2.R*Weight2;
  NewRYB.Y:=Color1.Y*Weight1+Color2.Y*Weight2;
  NewRYB.B:=Color1.B*Weight1+Color2.B*Weight2;
  K:=MaxValue([NewRYB.R,NewRYB.Y,NewRYB.B]);
  NewRYB.R:=NewRYB.R/K;
  NewRYB.Y:=NewRYB.Y/K;
  NewRYB.B:=NewRYB.B/K;
end;

Ну, или, если представить себе каждый цвет как вектор в трехмерном пространстве, то в Delphi процедуру сложения двух RYB-цветов можно сделать ещё короче:

var Color1, Color2, NewColor: TVector3D;
begin
  NewColor:=Color1.Scale(Weight1)+Color2.Scale(Weight2);
  Vector3:=Vector3.Scale(1/MaxValue([NewColor.X,NewColor.Y,NewColor.Z]));
end;

В результате получим какой-то новый цвет в RYB. Как его теперь показать пользователю? Естественно, тут мы выше головы не прыгнем и нам надо будет как-то конвертировать RYB в RGB. Поиски в сети на предмет конвертеров из RYB в RGB наткнулся вот на такой замечательный кубик:

Куб для интерполяции RYB

Куб для интерполяции RYB

Используя этот кубик, ребята вот с этого сайта собрали простенький калькулятор на JavaScript, который переводит любой цвет из RYB в RGB. Ну, а раз у нас есть скрипт, то не вижу смысла изобретать свой велосипед — просто переведем этот скрипт на рельсы Delphi:

function RYBToARGB(RYBColor: TRYBColor):TAlphaColor;
function CubicInt(t,a,b: single): single;
var Weight: single;
begin
  Weight:=t*t*(3-2*t);
  Result:=A+Weight*(B-A);
end;
 
function GetRValue: integer;
var x0, x1, x2, x3, y0, y1: single;
begin
  x0:=CubicInt(RYBColor.B,1,0.163);
  x1:= cubicInt(RYBColor.B, 1.0, 0.0);
	x2:= cubicInt(RYBColor.B, 1.0, 0.5);
	x3:= cubicInt(RYBColor.B, 1.0, 0.2);
	y0:= cubicInt(RYBColor.Y, x0, x1);
	y1:= cubicInt(RYBColor.Y, x2, x3);
  Result:=ceil(255 * cubicInt(RYBColor.R, y0, y1));
end;
 
function GetGValue:integer;
var x0, x1, x2, x3, y0, y1: single;
begin
  x0:=cubicInt(RYBColor.B, 1.0, 0.373);
 	x1:=cubicInt(RYBColor.B, 1.0, 0.66);
 	x2:=cubicInt(RYBColor.B, 0.0, 0.0);
 	x3:=cubicInt(RYBColor.B, 0.5, 0.094);
 	y0:=cubicInt(RYBColor.Y, x0, x1);
 	y1:=cubicInt(RYBColor.Y, x2, x3);
 	Result:=ceil(255 * cubicInt(RYBColor.R, y0, y1));
end;
 
function GetBValue:integer;
var x0, x1, x2, x3, y0, y1: single;
begin
  x0:= cubicInt(RYBColor.B, 1.0, 0.6);
  x1:= cubicInt(RYBColor.B, 0.0, 0.2);
  x2:= cubicInt(RYBColor.B, 0.0, 0.5);
  x3:= cubicInt(RYBColor.B, 0.0, 0.0);
  y0:= cubicInt(RYBColor.Y, x0, x1);
  y1:= cubicInt(RYBColor.Y, x2, x3);
  result:=ceil(255*cubicInt(RYBColor.R, y0, y1));
end;
 
begin
  Result:=MakeColor(GetRValue,
                    GetGValue,
                    GetBValue)
end;

Имея в руках две функции — сложения RYB-цветов и конвертирования из RYB в ARGB мы можем проверить нашу работу и нарисовать собственное цветовое колесо RYB.

Приложение «Цветовое колесо RYB»

Чтобы продемонстрировать работу с RYB я написал небольшую программку, которая, используя приведенные выше методы, смешивает выбранные краски и показывает значения RGB и RYB полученной смеси. Ниже небольшой видео-ролик, демонстрирующий работу программы:

[youtube_sc url=»https://www.youtube.com/watch?v=w-Bc-lqYw7c»]

Конечно, RYB обладает своими недостатками, но, тем не менее, эта цветовая модель нашла свое применение в изобразительном искусстве.

Пока разбирался с задачей смешения цветов перебрал практически все известные цветовые модели, поэтому, думаю, что тема работы с цветами в блоге WebDelphi ещё не закончена и, вполне возможно, что «Цветовое колесо RYB» немного разрастется.

На этом все. Всем удачи и до новых встреч на страницах блога WebDelphi.ru.

5 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
6 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Владислав Андреев

Что в данном случае значит Вес(количество цвета)?
а количество (или вес) в общей массе как

weight1, weight2: single

Владислав Андреев
Ответить на  Vlad

Это получается weight это (R + Y + B)?

Спасибо огромное за ответ

Владислав Андреев

Это получается weight это (R + Y + B)?

Василий Кошкин
16/04/2016 23:05

Владислав (Vlad), я очень туго программирую. Я просто восхищен этой программкой — просто, легко и удобно. Но очень хотелось бы разместить такую же программку, как на видео, у себя на сайте. Может на каком-то сайте это реализовано? Все что я нашел в сети, это модель усреднения. И при сложении синего с желтым получается серый. Это, конечно же не то. Хотел написать в личку, не найду Ваш e-mail.