c++ - HSL 到 RGB 颜色转换问题

标签 c++ colors rgb hsl

我喜欢随机生成 - 和随机颜色 - 所以我决定将它们结合起来制作一个简单的二维景观生成器。我的想法是,根据方 block 的高度(是的,地形是由方 block 组成的)使它更亮或更暗,靠近顶部的东西更亮,靠近底部的东西更暗。我让它在灰度下工作,但正如我发现的那样,你不能真正使用基本 RGB 颜色并使其更亮,因为 RGB 值之间的比率或任何类似的东西似乎无法使用。解决方案?华硕。或者可能是 HSV,老实说,我仍然不知道其中的区别。我指的是 H 0-360,S & V/L = 0-100。虽然...嗯,360 = 0,所以也就是360个值,但是如果你真的有0-100,那就是101。难道真的是0-359和1-100(还是0-99?),但是颜色选择编辑器(目前指的是 GIMP...MS 画图的饱和度超过 100)允许您输入这样的值吗?

无论如何,我找到了 HSL->RGB 转换的公式 ( here & here 。据我所知,最终的公式是相同的,但我还是会提供代码(请注意,这是来自后者 easyrgb.com 链接):

Hue_2_RGB

float Hue_2_RGB(float v1, float v2, float vH)             //Function Hue_2_RGB
{
if ( vH < 0 )
    vH += 1;

if ( vH > 1 )
    vH -= 1;

if ( ( 6 * vH ) < 1 )
    return ( v1 + ( v2 - v1 ) * 6 * vH );

if ( ( 2 * vH ) < 1 )
    return ( v2 );

if ( ( 3 * vH ) < 2 )
    return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 );

return ( v1 );
}

和另一段代码:

float var_1 = 0, var_2 = 0;

        if (saturation == 0)                       //HSL from 0 to 1
        {
           red = luminosity * 255;                      //RGB results from 0 to 255
           green = luminosity * 255;
           blue = luminosity * 255;
        }
        else
        {
            if ( luminosity < 0.5 )
                var_2 = luminosity * (1 + saturation);
            else
                var_2 = (luminosity + saturation) - (saturation * luminosity);

            var_1 = 2 * luminosity - var_2;

            red = 255 * Hue_2_RGB(var_1, var_2, hue + ( 1 / 3 ) );
            green = 255 * Hue_2_RGB( var_1, var_2, hue );
            blue = 255 * Hue_2_RGB( var_1, var_2, hue - ( 1 / 3 ) );
        }

抱歉,不确定修复这些空格的好方法。

我用自己的名字、色调、饱和度和亮度替换了 H、S、L 值。我回头看了看,但除非我遗漏了什么,否则我会正确地更换它。但是,除了 C++ 所需的部分之外,hue_2_RGB 函数是完全未经编辑的。 (例如变量类型)。我也曾经对所有东西都有整数 - R,G,B,H,S,L - 然后它发生在我身上...... HSL 是公式的 float - 或者至少,它看起来应该是。所以我使用变量(var_1、var_2、所有 v、R、G、B、色调、饱和度、亮度)来 float 。所以我不相信这是某种数据丢失错误。此外,在输入公式之前,我有色调/= 360、饱和度/= 100 和亮度/= 100。请注意,在此之前,我有色调 = 59、饱和度 = 100 和亮度 = 70。我相信我得到了色调正确为 360 以确保 0-1,但尝试/= 100 也没有解决它。

所以,我的问题是,为什么公式不起作用?如果您能提供帮助,谢谢。

编辑:如果问题不清楚,请发表评论。

最佳答案

你的前提是错误的。您可以只缩放 RGB 颜色。例如,Java 中的 Color 类包括名为 .darker() 和 .brighter() 的命令,它们使用 0.7 的因子,但您可以使用任何您想要的值。

public Color darker() {
    return new Color(Math.max((int)(getRed()  *FACTOR), 0),
                     Math.max((int)(getGreen()*FACTOR), 0),
                     Math.max((int)(getBlue() *FACTOR), 0),
                     getAlpha());
}

public Color brighter() {
    int r = getRed();
    int g = getGreen();
    int b = getBlue();
    int alpha = getAlpha();

    /* From 2D group:
     * 1. black.brighter() should return grey
     * 2. applying brighter to blue will always return blue, brighter
     * 3. non pure color (non zero rgb) will eventually return white
     */
    int i = (int)(1.0/(1.0-FACTOR));
    if ( r == 0 && g == 0 && b == 0) {
        return new Color(i, i, i, alpha);
    }
    if ( r > 0 && r < i ) r = i;
    if ( g > 0 && g < i ) g = i;
    if ( b > 0 && b < i ) b = i;

    return new Color(Math.min((int)(r/FACTOR), 255),
                     Math.min((int)(g/FACTOR), 255),
                     Math.min((int)(b/FACTOR), 255),
                     alpha);
}

简而言之,将所有三种颜色乘以相同的静态因子,您将得到相同的颜色比例。这是一个有损操作,您需要确保压接颜色以保持在范围内(这比舍入误差更有损)。

坦率地说,从 RGB 到 HSV 的任何转换都只是数学运算,更改 HSV V 因子只是数学运算,将其改回更像是数学运算。你不需要这些。你可以做数学。这将使最大分量颜色更大,而不会弄乱颜色之间的比例。

--

如果问题更具体,而您只是想要更好的结果。有更好的方法来计算这个。您可以转换为亮度分量,而不是静态缩放亮度(L 不是指亮度)。基本上以特定方式加权。色彩科学和计算与人类观察者打交道,他们比实际的数学更重要。为了解释其中的一些人类怪癖,需要“修复事物”以使其与普通人的感知更相似。亮度缩放如下:

Y = 0.2126 R + 0.7152 G + 0.0722 B

这同样反射(reflect)在权重 30、59、11 中,它们被错误地认为是良好的颜色距离权重。这些权重是颜色对人类亮度感知的贡献。例如,人类认为最亮的蓝色非常暗。而黄色(与蓝色完全相反)看起来太亮了,以至于你甚至无法在白色背景下辨认出来。 Y'CbCr 包含的许多色彩空间通过缩放解释了亮度感知中的这些差异。然后您可以更改该值,当您缩小它时它会再次缩放。

导致不同的颜色,这应该更类似于人类所说的相同颜色的“较浅”版本。这个人类系统的近似值越来越好,因此使用更好、更高级的数学来解释它通常会给你带来越来越好的结果。

对于涉及这些问题的良好概述。 http://www.compuphase.com/cmetric.htm

关于c++ - HSL 到 RGB 颜色转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12203783/

相关文章:

java - ListView 更改文本中的文本颜色

python - 图像的 RGB 立方体

imagemagick - 如何从 ImageMagick 导出多个文件的详细结果

c++ - 未初始化的值是由堆栈分配创建的 - Qt - C++

c++ - 字符数组和指针

image - 编写颜色配置文件以跨多个扫描仪标准化颜色

ios - CAEmitterCell 颜色属性不起作用

C#和Matlab读取视频帧rgb值的区别

c++ - 向标准模板的特化添加新方法(std::vector、std::list...)

c++ - 我怎样才能得到一个函数来调用调用它的函数?