Преобразование цветов RGB в HSB - PullRequest
7 голосов
/ 05 ноября 2010

Я пытаюсь преобразовать цвет HSB в RGB.Я делаю так:

System.Windows.Media.Color winColor = value;
System.Drawing.Color drawColor = System.Drawing.Color.FromArgb(winColor.R, winColor.G, winColor.B);
Hue = (byte)(drawColor.GetHue()*255);
Saturation = (byte)(drawColor.GetSaturation()*255);
Luminosity = (byte)(drawColor.GetBrightness()*255);

Я обнаружил, что когда у меня есть FF0000, он будет преобразован в H = 0, S = 255, L = 127, который преобразуется в RGB FF0E0E.Я думаю, что светимость должна быть 120?Или я неправильно понимаю весь HSB?Когда я смотрю на палитру цветов в Photoshop, оттенок 0-360 градусов, насыщенность, яркость 0-100%.У меня значения HSB от 0 до 255, я делаю это неправильно?

Ответы [ 3 ]

11 голосов
/ 05 ноября 2010

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

Существует разница между HSL и HSB (он же HSV).

Таким образом, вы не можете взять (B) правильность из цветового класса и использовать его как (L) унизительность.

Чтобы вернуться из класса Color к значениям GetHue(), GetSaturation() и GetBrightness() к обычному цвету, вы должны дать этому методу расширения шанс.

/// <summary>
/// Creates a Color from alpha, hue, saturation and brightness.
/// </summary>
/// <param name="alpha">The alpha channel value.</param>
/// <param name="hue">The hue value.</param>
/// <param name="saturation">The saturation value.</param>
/// <param name="brightness">The brightness value.</param>
/// <returns>A Color with the given values.</returns>
public static Color FromAhsb(int alpha, float hue, float saturation, float brightness)
{
    if (0 > alpha
        || 255 < alpha)
    {
        throw new ArgumentOutOfRangeException(
            "alpha",
            alpha,
            "Value must be within a range of 0 - 255.");
    }

    if (0f > hue
        || 360f < hue)
    {
        throw new ArgumentOutOfRangeException(
            "hue",
            hue,
            "Value must be within a range of 0 - 360.");
    }

    if (0f > saturation
        || 1f < saturation)
    {
        throw new ArgumentOutOfRangeException(
            "saturation",
            saturation,
            "Value must be within a range of 0 - 1.");
    }

    if (0f > brightness
        || 1f < brightness)
    {
        throw new ArgumentOutOfRangeException(
            "brightness",
            brightness,
            "Value must be within a range of 0 - 1.");
    }

    if (0 == saturation)
    {
        return Color.FromArgb(
                            alpha,
                            Convert.ToInt32(brightness * 255),
                            Convert.ToInt32(brightness * 255),
                            Convert.ToInt32(brightness * 255));
    }

    float fMax, fMid, fMin;
    int iSextant, iMax, iMid, iMin;

    if (0.5 < brightness)
    {
        fMax = brightness - (brightness * saturation) + saturation;
        fMin = brightness + (brightness * saturation) - saturation;
    }
    else
    {
        fMax = brightness + (brightness * saturation);
        fMin = brightness - (brightness * saturation);
    }

    iSextant = (int)Math.Floor(hue / 60f);
    if (300f <= hue)
    {
        hue -= 360f;
    }

    hue /= 60f;
    hue -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f);
    if (0 == iSextant % 2)
    {
        fMid = (hue * (fMax - fMin)) + fMin;
    }
    else
    {
        fMid = fMin - (hue * (fMax - fMin));
    }

    iMax = Convert.ToInt32(fMax * 255);
    iMid = Convert.ToInt32(fMid * 255);
    iMin = Convert.ToInt32(fMin * 255);

    switch (iSextant)
    {
        case 1:
            return Color.FromArgb(alpha, iMid, iMax, iMin);
        case 2:
            return Color.FromArgb(alpha, iMin, iMax, iMid);
        case 3:
            return Color.FromArgb(alpha, iMin, iMid, iMax);
        case 4:
            return Color.FromArgb(alpha, iMid, iMin, iMax);
        case 5:
            return Color.FromArgb(alpha, iMax, iMin, iMid);
        default:
            return Color.FromArgb(alpha, iMax, iMid, iMin);
    }
}

Обновление

Так что просто, чтобы прояснить ситуацию. Мой код выше и три метода в классе Color, упомянутом выше, используют цветовую модель HSB (иначе HSV), но Photoshop использует цветовую модель HSL.

В своем комментарии вы написали, что параметры Hue = 0, Saturation = 1 и Brightness = 1 дают вам код над красным цветом и белым в Photoshop. Если вы внимательно посмотрите на различия между этими режимами, это абсолютно логично:

Цилиндр HSL

HSL cylinder

  • В обеих моделях оттенок действует одинаково, используя красный цвет в качестве начальной и конечной точки (ноль и 360 градусов).
    • Просто глядя на оттенок, вы получаете красный цвет.
  • Насыщенность определяет, насколько непрозрачный цвет или какова доля белой шкалы.
    • Так что, установив его на одно, вы говорите, что хотите получить полный блестящий красный цвет.
  • Подсветка теперь определяет, сколько черного и белой части в вашем цвете. Установив его на ноль, вы получите черный, один означает белый, а 0,5 означает идеальный вес.
    • Так что, установив его на одно, вы говорите, что хотите, чтобы он был максимально ярким, в результате чего получается белый цвет.

цилиндр HSB

HSB cylinder

  • В обеих моделях оттенок действует одинаково, используя красный цвет в качестве начальной и конечной точки (ноль и 360 градусов).
    • Просто глядя на оттенок, вы получаете красный цвет.
  • Насыщенность определяет, насколько непрозрачный цвет или сколько составляет часть белой шкалы.
    • Так что, установив его на одно, вы говорите, что хотите получить полный блестящий красный цвет.
  • Яркость (или значение) теперь определяет, сколько составляет черная часть в цвете (не белая часть).
    • Таким образом, установив его на одно, вы говорите, что хотите, чтобы он был полноцветным, приводя к полностью блестящему красному цвету.

Как видите, Photoshop и .Net Framework (включая мою функцию расширения) используют разные модели раскраски. Поэтому вам следует проверить, не нашли ли вы где-нибудь реализацию другой модели раскраски, преобразования или чего-то еще, что дает вам необходимые результаты.

3 голосов
/ 17 августа 2013

Это работает ... модифицировано из исходного кода Java.Другой ответ - все еще HSL. Это действительно HSB для RGB (на самом деле это HSB / HSV для System.Windows.Media.Color в качестве типа моего возврата)

    public static Color HSBtoRGB(float hue, float saturation, float brightness)
    {
        int r = 0, g = 0, b = 0;
        if (saturation == 0)
        {
            r = g = b = (int)(brightness * 255.0f + 0.5f);
        }
        else
        {
            float h = (hue - (float)Math.Floor(hue)) * 6.0f;
            float f = h - (float)Math.Floor(h);
            float p = brightness * (1.0f - saturation);
            float q = brightness * (1.0f - saturation * f);
            float t = brightness * (1.0f - (saturation * (1.0f - f)));
            switch ((int)h)
            {
                case 0:
                    r = (int)(brightness * 255.0f + 0.5f);
                    g = (int)(t * 255.0f + 0.5f);
                    b = (int)(p * 255.0f + 0.5f);
                    break;
                case 1:
                    r = (int)(q * 255.0f + 0.5f);
                    g = (int)(brightness * 255.0f + 0.5f);
                    b = (int)(p * 255.0f + 0.5f);
                    break;
                case 2:
                    r = (int)(p * 255.0f + 0.5f);
                    g = (int)(brightness * 255.0f + 0.5f);
                    b = (int)(t * 255.0f + 0.5f);
                    break;
                case 3:
                    r = (int)(p * 255.0f + 0.5f);
                    g = (int)(q * 255.0f + 0.5f);
                    b = (int)(brightness * 255.0f + 0.5f);
                    break;
                case 4:
                    r = (int)(t * 255.0f + 0.5f);
                    g = (int)(p * 255.0f + 0.5f);
                    b = (int)(brightness * 255.0f + 0.5f);
                    break;
                case 5:
                    r = (int)(brightness * 255.0f + 0.5f);
                    g = (int)(p * 255.0f + 0.5f);
                    b = (int)(q * 255.0f + 0.5f);
                    break;
            }
        }
        return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
    }
0 голосов
/ 23 февраля 2019

Поскольку другие ответы, похоже, не работают для меня (и у меня не хватило терпения посмотреть, что происходит), я делюсь своим кодом для преобразования HSV-> RGB.Он основан на разделе «Альтернативное преобразование ВПГ» в Википедии и довольно компактен.

public static Color FromAhsv(byte alpha, float hue, float saturation, float value)
{
    if (hue < 0f || hue > 360f)
        throw new ArgumentOutOfRangeException(nameof(hue), hue, "Hue must be in the range [0,360]");
    if (saturation < 0f || saturation > 1f)
        throw new ArgumentOutOfRangeException(nameof(saturation), saturation, "Saturation must be in the range [0,1]");
    if (value < 0f || value > 1f)
        throw new ArgumentOutOfRangeException(nameof(value), value, "Value must be in the range [0,1]");

    int Component(int n)
    {
        var k = (n + hue / 60f) % 6;
        var c = value - value * saturation * Math.Max(Math.Min(Math.Min(k, 4 - k), 1), 0);
        var b = (int)Math.Round(c * 255);
        return b < 0 ? 0 : b > 255 ? 255 : b;
    }

    return Color.FromArgb(alpha, Component(5), Component(3), Component(1));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...