8 votes

Conversion des couleurs RVB en couleurs HSB

J'essaie de convertir une couleur HSB en RGB. Voici comment je procède

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

Je trouve que lorsque j'ai FF0000 il sera converti en H = 0, S = 255, L = 127 qui convertit en RGB FF0E0E . Je pense que la luminosité devrait être de 120 ? Ou bien est-ce que je me trompe sur l'ensemble du HSB ? Lorsque je regarde le sélecteur de couleurs dans Photoshop, la teinte est de 0 à 360 degrés, la saturation et la luminosité de 0 à 100 %. J'ai des valeurs HSB allant de 0 à 255, est-ce que je m'y prends mal ?

14voto

Oliver Points 19006

Peut-être avez-vous déjà examiné cette question article de wikipédia mais pour que ce soit clair.

Il y a une différence entre HSL et HSB (alias HSV).

Vous ne pouvez donc pas prendre la (B)justesse de la classe de couleur et l'utiliser comme une (L)uminosité.

Pour récupérer les valeurs fournies par la classe de couleur GetHue() , GetSaturation() y GetBrightness() à une couleur normale, vous devriez donner une chance à cette méthode d'extension.

/// <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);
    }
}

Mise à jour

Donc, pour que les choses soient claires. Mon code ci-dessus et les trois méthodes de la classe Color mentionnées ci-dessus utilisent le modèle de couleur HSB (aka HSV), mais Photoshop utilise le modèle de couleur HSL.

Dans votre commentaire, vous avez écrit que les paramètres Hue = 0 , Saturation = 1 y Brightness = 1 vous donner avec le code ci-dessus une couleur rouge et blanche dans Photoshop. Lorsque vous regardez de plus près les différences de ces modes, cela est tout à fait logique :

Le cylindre HSL

HSL cylinder
(source : <a href="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/HSL_color_solid_cylinder_alpha_lowgamma.png/197px-HSL_color_solid_cylinder_alpha_lowgamma.png" rel="nofollow noreferrer">wikimedia.org </a>)

  • Dans les deux modèles, la teinte agit de la même manière en utilisant la couleur rouge comme point de départ et d'arrivée (zéro et 360 degrés).
    • En regardant simplement la teinte, vous avez une couleur rouge.
  • La saturation définit comment opaque de la couleur ou de la portion de l'échelle des blancs.
    • Donc, en le réglant sur un, vous dites que vous voulez une couleur rouge pleine et brillante.
  • L'éclairage définit maintenant à quel point le noir et la partie blanche dans votre couleur. En le réglant sur zéro, vous obtenez du noir, un signifie du blanc et 0,5 signifie une pondération parfaite.
    • En le réglant sur un, vous dites que vous voulez qu'il soit aussi lumineux que possible, ce qui donne une couleur blanche.

Le cylindre HSB

HSB cylinder
(source : <a href="https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/HSV_color_solid_cylinder_alpha_lowgamma.png/197px-HSV_color_solid_cylinder_alpha_lowgamma.png" rel="nofollow noreferrer">wikimedia.org </a>)

  • Dans les deux modèles, la teinte agit de la même manière en utilisant la couleur rouge comme point de départ et d'arrivée (zéro et 360 degrés).
    • En regardant simplement la teinte, vous avez une couleur rouge.
  • La saturation définit comment opaque de la couleur ou de la portion de l'échelle des blancs.
    • Donc, en le réglant sur un, vous dites que vous voulez une couleur rouge pleine et brillante.
  • La luminosité (ou valeur) définit maintenant la part de noir dans la couleur (et non la part de blanc).
    • Donc, en le réglant sur un, vous dites que vous voulez qu'il soit entièrement coloré, ce qui donne une couleur rouge brillante.

Comme vous pouvez le constater, Photoshop et le cadre .Net (y compris ma fonction d'extension) utilisent des modèles de coloration différents. Vous devriez donc vérifier si vous trouvez quelque part une implémentation de l'autre modèle de coloration, une transformation ou autre chose qui vous donne les résultats dont vous avez besoin.

3voto

Chuck Rostance Points 1377

Cela fonctionne... modifié à partir du code source Java. L'autre réponse est toujours HSL, c'est vraiment HSB vers RGB (en fait c'est HSB/HSV vers System.Windows.Media.Color comme mon type de retour).

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

0voto

loreggia Points 188

Puisque les autres réponses ne semblent pas fonctionner pour moi (et que je n'ai pas eu la patience de voir ce qui se passe), je partage mon code pour la conversion HSV->RGB. Il est basé sur la section "Alternate HSV conversion" sur Wikipedia et est assez compact.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X