я пытаюсь заполнить массив градиентом радуги. Массив должен содержать 256 записей, заполненных шестнадцатеричным значением цветов.
лайк:
array[0] = 0xFF0000 //red
...
array[85] = 0xFFA200 //orange
...
array[170] = 0x00AF0F //green
...
array[255] = 0xAE00FF //purple
потому что я не хочу назначать все 256 цветов «вручную» массиву, я ищу динамический подход для этого. Это не обязательно должен быть ранг, показанный выше. Картина только для демонстрации.
Любые предложения, как сделать такие вещи в (предпочтительно) коротком фрагменте кода, избегая пары вложенных циклов?
Вы хотите перейти от красного к желтому
Далее от желтого до зеленого
Далее от зеленого до светло-голубого
Далее от светло-голубого до темно-синего цвета
Далее темно-синий или фиолетовый
И вернемся к красному.
На каждом проходе один из цветов равен нулю, а другой — 255, в то время как последний цвет увеличивается или уменьшается. Другими словами:
255,0,0 -> 255,255,0 -> 0,255,0 -> 0,255,255 -> 0,0,255 -> 255,0,255 -> 255,0,0
Это можно сделать с помощью следующего кода, где диапазон оттенков находится между 0.0f
в 1.0f
unsigned int rgb(double hue)
{
int h = int(hue * 256 * 6);
int x = h % 0x100;
int r = 0, g = 0, b = 0;
switch (h / 256)
{
case 0: r = 255; g = x; break;
case 1: g = 255; r = 255 - x; break;
case 2: g = 255; b = x; break;
case 3: b = 255; g = 255 - x; break;
case 4: b = 255; r = x; break;
case 5: r = 255; b = 255 - x; break;
}
return r + (g << 8) + (b << 16);
}
Использование:
double range = 500;
for (double i = 0; i < range; i++)
{
unsigned int color = rgb(i / range);
...
}
Выход:
Один из способов сделать то, что вы хотите, это интерполировать каждый из цветов компонента (RGB) от их начального до конечного значения. Это означает использование шагов одинакового размера, насколько это возможно.
Чтобы получить компоненты RGB, необходимо немного манипулировать битами. Этот код дает вам три компонента цвета для полностью заявленного цвета fullColour
:
std::array<float, 3> colourRGB;
for(unsigned i = 0; i<3; ++i) {
colourRGB[i] = (fullColour & (0xFF << (i*8))) >> (i*8);
Вы используете это, чтобы получить массив RGB вашего начального и конечного цвета (например, для красно-оранжевого диапазона в вашем примере это будет разбивка RGB 0xFF0000
а также 0xFFA200
). Для каждого компонента вы затем определяете размер шага, требуемый для каждого шага в вашем «исчезновении». Это дается общим изменением в этом компоненте, деленным на общее количество шагов. Для красно-оранжевого примера размер шага для компонента Red будет, таким образом, 1,91 (потому что у вас есть 86 шагов и общее изменение (0xA2
— 0x00
или 162 в десятичном виде, что дает 162/86 = 1,91). Размеры шагов для других компонентов равны нулю, поскольку они не меняются.
Затем вы можете перебирать шаги, добавляя каждый размер шага и округляя, чтобы получить новое значение для каждого компонента. Например, на шаге s
:
red[s] = startingRed + ((float)s * stepSizeRed)
Чтобы снова объединить ваши значения RGB в полный цвет, просто примените немного битовых манипуляций снова:
fullColour[s] = 0;
for(unsigned i=0; i<3; ++i)
fullColour[s] += rgbComponent[s][i] << (i*8);
Этот подход дает требуемое «исчезновение» от любого начального до любого конечного цвета за любое количество шагов.