как правильно сгенерить цвета радуги?

Elina74

сейчас я делаю так:
стрелочка а->бэ означает, что в цикле происходит изменение от а к бэ по единичке
1) красный -> желтый
r = 255
g = 0->255
b = 0
2) желтый -> зеленый
r = 255 -> 0
g = 255
b = 0
3) зеленый -> голубой
r = 0
g = 255
b = 0 -> 255
4) голубой -> синий
r = 0
g = 255 -> 0
b = 255
5) синий -> фиолетовый
r = 0 -> 255
g = 0
b = 255
Итого получается массив из 256*5 = 1280 ячеек, который заполняется за аналогичное число шагов.
Есть ли способ попроще, если мне, скажем, нужен массив всего из 10 цветов, а все остальные не нужны? Понятно, что можно сначала сгенерить этот массив из 1280 цветов, потом линейно его "наложить" на этот 10-ячеечный массив. А попроще?

sbs-66

Это глубокий филосовский вопрос и он имеет множество решений.
Самый научный - найти графики чувствительности всяких палочек и колбочек к цветам в зависимости от длины волны и научиться, соответсвено переводить лину волны в RGB, после чего взять равномерно распределённые N точек с длинами волны от красного до фиолетового, которые имеют место быть в радуге, и перевести их в RGB.
Самый простой - открыть паинт, открыть инструмент для выбора цвета, тыкнуть в нескольких местах в тамошнюю радугу, записать и пользоваться той таблицей. Ну, или через WinAPI сделать то же самое (хотя то, что ты описал, я думаю, в целом примерно повторяет процедуры, которые винда будет делать, переводя цвета из цветового пространства [оттенок, контраст, яркость] (не помню как оно зовётся по науке) в RGB.

Elina74

За первую часть спасибо, я более-менее осведомлён в нём, но научными исследованиями заниматься в этой области не намерен.
За вторую тоже спасибо, но это же мне надо программно сделать. В моём посте описано, как я это делаю сейчас и хотел бы описания примерно на том же уровне.

sbs-66

Ну не генери массив, а сразу посмотри, куда у тебя нужные N точек попадут. Есть отрезок длины 5, который делится на N - 1 частей. Ну, пусть N=13. Получаем точки
0
5/12
10/12
1+3/12
1+8/12
2+1/12, ...
Получаются цвета
FF0000
FF6A00 (6A = 255 * 5 / 12 )
FFD400
BFFF00 (BF = 255 - 255 * 3 / 12 )
...
Только вот я не уверен, что от красного до жёлтого растояние 1 надо брать. Там же ещё оранжевый должен поместиться. Может быть надо взять 2. А вообще это уже к методу 1 вопрос, конечно, как там надо эти отрезки поделить.
PS. Второй способ я писал, чтобы сказать, что в WinAPI скорее всего есть нужная тебе функция, которая цвета из одного цветового пространства переводит в другое.

feliks28

Взять HSV и гонять по H, а потом перевести нужные 10 точек в RGB?

sbs-66

Во, я это и имел ввиду, только HSV забыл как называется.

feliks28

Да, похоже. Только ни промежуточные таблицы, ни виндовые функции не нужны. Перевод и так простой, а учитывая, что S и V в данном случае константы, так тем более.

Elina74

ага, как я понял из общения с пэйнтом, можно задать s=240, v=120 и, меняя h от 0 до 240, можно получить ту же радугу...
а это правда, что h = оттенок, s = контраст, v = яркость ?

feliks28

Если v=120, то это HSL(тон, насыщенность и яркость.) - там чистые цвета на 0.5
wiki: HSV, HSL

sbs-66

ни виндовые функции не нужны. Перевод и так простой, а учитывая, что S и V в данном случае константы, так тем более.
Тогда перевод превратиться в то же самое деление на отрезки и линейную интерполяцию на нужном отрезке, что автор по сути и делает.

feliks28

Зачем еще интерполяция? 10 отдельных точек.

sbs-66

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

feliks28

А, ты про основные цвета? Я не понял сначала.
Ну да, то же самое, просто с выписанным алгоритмом. Но с RGB по другому-то вроде и не сделать...

sbs-66

О, я так и думал, что кто-то такой фигнёй наверняка уже занимался. Сеньк за ссылку.

Elina74

короче, я сделал, вот вам часть боевого промышленного кода :grin:

double A = 255/(N-1);
for(int i=0; i<N; i++){
Color.setHsv(int(i*A 240, 240);
newItem = new QTableWidgetItem(Color.name;
brush = new QBrush(Color);
newItem->setBackground(*brush);
table->setItem(i, 2, newItem);
}
Оставить комментарий
Имя или ник:
Комментарий: