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

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

Язык - это С# с .net 3.5.

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

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

Ответы

Ответ 1

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

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

Ответ 2

В 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 );

Ответ 3

HSV (Hue/Saturation/Value), также называемый HSL (Hue/Saturation/Lightness), представляет собой просто другое цветовое представление.

Используя это представление, проще настроить яркость. Итак, конвертируйте из 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;
}

Ответ 4

Rich Newman обсуждает цвет HSL в отношении .NET System.Drawing.Color в своем блоге и даже предоставляет класс HSLColor, который выполняет всю работу за вас. Преобразуйте свой System.Drawing.Color в HSLColor, добавьте/вычтите значения против Luminosity и перейдите обратно в System.Drawing.Color для использования в вашем приложении.

Ответ 5

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

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

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

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

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

Ответ 6

Я использовал ControlPaint.Dark() и .Light() в System.Windows.Forms.

Ответ 7

Я предполагаю, что вы используете 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 черного цвета, который, будучи всеми нулями, облегчает математику.

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

Если ваши цвета находятся в формате 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 Unleashed как хорошее и полное введение в WPF.

НТН

Ответ 11

Любые изменения цвета лучше делать в HSL/HSV.

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

Ответ 12

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

Ответ 13

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