Как мне определить более темный или светлый цветовой вариант данного цвета?

StackOverflow https://stackoverflow.com/questions/97646

  •  01-07-2019
  •  | 
  •  

Вопрос

Учитывая исходный цвет любого оттенка системой или пользователем, я хотел бы получить простой алгоритм, который я мог бы использовать для разработки более светлых или более темных вариантов выбранного цвета.Аналогично эффектам, используемым в Windows Live Messenger для оформления пользовательского интерфейса.

Язык - C # с .net 3.5.

Отвечая на комментарий: Цветовой формат - (Alpha) RGB.Со значениями в виде байтов или чисел с плавающей точкой.

Отмечающий ответ: Для контекста моего использования (несколько простых эффектов пользовательского интерфейса) ответ, который я отмечаю как принятый, на самом деле самый простой для данного контекста.Тем не менее, я также отказался от голосов за более сложные и точные ответы.Любой, кто выполняет более сложные операции с цветом и найдет эту тему в будущем, обязательно должен проверить их.БОЛЬШОЕ спасибо.:)

Это было полезно?

Решение

Просто умножьте значения RGB на величину, на которую вы хотите изменить уровень.Если один из цветов уже имеет максимальное значение, то вы не сможете сделать его ярче (в любом случае, используя математику HSV).)

Это дает точно такой же результат с гораздо меньшими математическими затратами, как переключение на HSV и последующее изменение V.Это дает тот же результат, что и переключение на HSL, а затем изменение L, если вы не хотите начать терять насыщенность.

Другие советы

В XNA существует Color.Lerp статический метод это делает это как разницу между двумя цветами.

Lerp это математическая операция между двумя числами с плавающей запятой, которая изменяет значение первого на величину разницы между ними.

Вот метод расширения, позволяющий сделать это с float:

public static float Lerp( this float start, float end, float amount)
{
    float difference = end - start;
    float adjusted = difference * amount;
    return start + adjusted;
}

Таким образом, простая операция lerp между двумя цветами с использованием RGB была бы:

public static Color Lerp(this Color colour, Color to, float amount)
{
    // start colours as lerp-able floats
    float sr = colour.R, sg = colour.G, sb = colour.B;

    // end colours as lerp-able floats
    float er = to.R, eg = to.G, eb = to.B;

    // lerp the colours to get the difference
    byte r = (byte) sr.Lerp(er, amount),
         g = (byte) sg.Lerp(eg, amount),
         b = (byte) sb.Lerp(eb, amount);

    // return the new colour
    return Color.FromArgb(r, g, b);
}

Примером применения этого может быть что-то вроде:

// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );

// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );

// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );

HSV (оттенок / Насыщенность / Значение), также называемый HSL (оттенок / Насыщенность / Яркость ), - это просто другое цветовое представление.

Используя это представление, легче регулировать яркость.Итак, преобразуйте из RGB в HSV, сделайте букву "V" ярче, затем преобразуйте обратно в RGB.

Ниже приведен некоторый C-код для преобразования

void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;

/* convert RGB to [0,1] */

r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;

max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));

pv[0] = max;

/* Calculate saturation */

if (max != 0.0)
    ps[0] = (max-min)/max;
else
    ps[0] = 0.0; 

if (ps[0] == 0.0)
{
    ph[0] = 0.0f;   //UNDEFINED;
    return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;

if (r==max)
{
    ph[0] = (g-b)/delta;
}
else if (g==max)
{
    ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
    ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
    ph[0] += 360.0;
}

void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;

if( s == 0 )
{
    // achromatic (grey)
    r = g = b = v;
}
else
{
    h /= 60;            // sector 0 to 5
    i = (int)floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i )
    {
    case 0:
        r = v;
        g = t;
        b = p;
    break;
    case 1:
        r = q;
        g = v;
        b = p;
    break;
    case 2:
        r = p;
        g = v;
        b = t;
    break;
    case 3:
        r = p;
        g = q;
        b = v;
    break;
    case 4:
        r = t;
        g = p;
        b = v;
    break;
    default:        // case 5:
        r = v;
        g = p;
        b = q;
    break;
    }
}
r*=255;
g*=255;
b*=255;

pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}

Рич Ньюмен обсуждается цвет HSL с уважением к системе .NET.Рисование.Раскрашивание в своем блоге и даже предоставляет класс HSLColor это сделает всю работу за вас.Преобразуйте систему.Рисунок.Цвет в HSLColor, добавьте / вычтите значения по отношению к яркости и преобразуйте обратно в систему.Рисунок.Цвет для использования в вашем приложении.

Вы можете преобразовать свой цвет в цветовое пространство HSL, манипулировать им там и преобразовать обратно в выбранное вами цветовое пространство (скорее всего, это RGB).

Более светлые цвета имеют более высокое значение L, более темные - более низкое.

Вот соответствующий материал и все уравнения:

http://en.wikipedia.org/wiki/HSL_color_space

Другой метод заключается в простой интерполяции вашего цвета с белым или черным.Это также немного обесцветит цвет, но это дешевле в расчете.

Я использовал ControlPaint.Dark() и .Light() в системе.Windows.Формы.

Я предполагаю, что вы используете RGB со значениями в байтах (от 0 до 255), поскольку это очень распространено повсюду.

Чтобы сделать изображение ярче, усредните значения RGB по значению RGB белого цвета.Или, чтобы иметь некоторый контроль над количеством осветляющих веществ, смешайте их в определенной пропорции.Пусть f изменяться от 0.0 до 1.0, тогда:

Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255

Для более темного цвета используйте цвет RGB черного цвета, который, будучи полностью нулевым, упрощает математику.

Я опускаю такие детали, как преобразование результата обратно в байты, что, вероятно, вы бы захотели сделать.

Если вы используете цвета RGB, я бы преобразовал эти параметры цвета в HSL (оттенок, насыщенность, яркость), измените параметр яркости, а затем преобразуйте обратно в RGB.Погуглите, и вы найдете множество примеров кода о том, как выполнять эти преобразования цветового представления (RGB в HSL и наоборот).

Это то, что я быстро нашел:http://bytes.com/forum/thread250450.html

Предполагая, что вы получаете цвет как RGB, сначала преобразуйте его в цветовое пространство HSV (оттенок, насыщенность, значение).Затем увеличьте / уменьшите значение, чтобы получить более светлый / темный оттенок цвета.Затем преобразуйте обратно в RGB.

Если ваши цвета представлены в формате RGB (или, предположительно, CMYK), вы можете использовать довольно грубый метод увеличения значения каждого компонента цвета.Например, в HTML цвета представлены в виде трех двузначных шестнадцатеричных чисел.#ff0000 даст вам ярко-красный цвет, который затем можно ослабить, увеличив значения компонентов G и B на ту же величину, например #ff5555 (дает более светлый красный цвет).Предположительно, для цветов Hue, Saturation и Lightness (HSL) вы можете просто увеличить компонент L, но я не могу сказать наверняка;Я менее знаком с этим цветовым пространством.

Однако, как я уже сказал, этот метод довольно грубый.Из моих воспоминаний о Live Messenger, похоже, что вы пытаетесь создавать градиенты, которые действительно довольно легко можно применить в Windows Presentation Foundation (WPF, часть .NET 3.0).WPF поддерживает множество различных типов градиентных кистей, включая линейные и радиальные градиенты.

Я могу очень порекомендовать книгу Адама Натана Выпущенный на свободу Windows Presentation Foundation в качестве хорошего и обстоятельного введения в WPF.

HTH

Любые вариации в цвете лучше выполнять в HSL / HSV.

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

Идея преобразования в HSV или какое-либо другое цветовое пространство кажется хорошей и может быть необходима для точной работы с цветом, но для обычных целей ошибки при работе в RGB может быть недостаточно, чтобы иметь значение.Кроме того, иметь дело с пограничными случаями может быть непросто:RGB - это пространство в форме куба, в то время как HSV - нет.При работе со значениями в байтах между пробелами могут быть сопоставления "много к одному" и "один ко многим".Это может быть проблемой, а может и не быть, в зависимости от приложения.YMMV

Это Веб-сайт обратите внимание, что вы можете использовать класс ControlPaint в системе BCL C #.Windows.Пространство имен Forms.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top