【问题标题】:changing rgb color values to represent a value改变 rgb 颜色值来表示一个值
【发布时间】:2009-09-14 21:05:14
【问题描述】:

我正在尝试在 java 中的画布上进行颜色更改,以表示由颜色表示的值相对于彼此的强弱程度。

rgb 颜色必须是相同的颜色,只是不同的色调,比如白色到灰色到黑色以及介于两者之间的每个灰色阴影。考虑到我所代表的值变化很大,从 -9999999 到正 9999999,如何更改 rgb 值。

【问题讨论】:

    标签: java


    【解决方案1】:

    我认为你应该看看 HSL/HSV 而不是 RGB。

    虽然 RGB 在本质上是基本的,因为它根据原色来表达颜色,但它不允许您对 R、G 或 B 值进行“可理解的”更改以达到“相似”的颜色。使用 HSL/HSV 模型,您将能够更改亮度/亮度/值 (L/V) 以获得具有不同灰色量的颜色,或更改色相 (H) 以获得整个光谱中的相似颜色.您可以从全亮度(白色)开始,通过降低 L/V 的值来创建较暗的灰色调,最终达到无亮度的颜色(黑色)。

    一个很温和的introduction to color theory, for developers is available here

    至于你的问题,你应该用 HSL 来表达你的颜色,随着饱和度值的增加,颜色范围从白色到黑色。当然,如果您想要介于白色和黑色之间的灰色调而不需要任何其他颜色,则应将色调保持在最低限度。

    下面是一个关于如何获得颜色范围的简短示例。为简洁起见,我已将颜色填充到数组中,但这不是必需的,因为您可能想立即使用颜色(除了考虑内存要求)。

    private Color[] produceColorRange(int steps)
    {
        float value = 1.0f; //Starting with full brightness
        Color[] colors = new Color[steps];
        for(int ctr = 0; ctr < steps; ctr++)
        {
            value = value - (1.0f/steps); //tend to darkness
            int rgb = Color.HSBtoRGB(0.7f, 0.0f, value); //create a darker color
                                                 //Hue is Blue, not noticeable
                                                 //because Saturation is 0
            Color color = new Color(rgb);
            colors[ctr] = color;
        }
        return colors;
    }
    

    如果你使用上面的方法并绘制一个JFrame,你将能够得到类似于下面的结果(除了我已经修改了色调和饱和度来得到我的颜色范围)。

    请注意,如果您想要更简单的方法来获取颜色范围,请使用 Color.WHITE 初始化 Color 对象并调用 color.darker()。当然,你将无法控制增量。

    【讨论】:

    • 这可能就是你想要的。 Paul 的解决方案可行,但只能提供 255 种不同的灰色,而且在 HSV 等其他色彩空间中最容易获得更多的灰色
    • 太好了,我在 JavaScript 中使用它。对于转换可以使用这个库:mjijackson.com/2008/02/…
    【解决方案2】:

    是的,调整您的价值观以适应您的领域。这取决于您的 RGB 值的存储方式。通常,每个使用 8 位。由于灰色具有 R = G = B,因此您希望将 (-9999999,9999999) 范围内的值缩放到 (0, 255)。

    考虑第一个区间中的 x。由于第一个范围也涵盖负数,因此首先进行移位。

    x = x + 9999999

    现在 x 在区间 (0, 19999998) 中。下一步是将其缩小到 (0, 255)。由于颜色值在该区间内呈线性增长,您所要做的就是:

    x = x * 255 / 19999998

    现在 x 就像你想要的那样在区间 (0, 255) 中。

    一般来说,如果你的初始值在区间 (a, b) 中,并且想要将其转换为 (0, c),应用这个公式:(注意 a 可以是负数)

    x = (x - a) * c / (b - a)

    因此,如果您的 R、G、B 值是 16 位长,则 c 将为 2**16 = 65536,公式为:

    x = (x + 9999999) * 65536 / 19999998

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      我不完全确定我理解你的问题,但是,如果我理解了:

      为什么不将 RGB 值缩放到您范围内的值(从 -9999999 到正 9999999)?此外,将 R、G 和 B 都设置为相同的值,以便您使用灰色阴影来表示值。

      像这样:

      private final int MIN = -9999999;
      private final int MAX = 9999999;
      
      public Color getScaledColor(int val) {
          int gray = (int) Math.round((double) (val - MIN) / (double) (MAX - MIN)
                  * 255.0);
          Color color = new Color(gray, gray, gray);
      
          return color;
      }
      

      请注意,此解决方案不会为您指定范围内的所有值提供唯一颜色。但也要记住,人眼只能区分这么多的阴影(而 2 * 9999999 + 1 可能比它可以区分的阴影数量多)。

      【讨论】:

        【解决方案4】:

        HSL Color 类实现上面提供的有关 HSL/HSV 的 Wikipedia 链接中提供的公式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-13
          • 1970-01-01
          • 2013-04-10
          • 2012-04-03
          • 1970-01-01
          • 1970-01-01
          • 2012-01-20
          相关资源
          最近更新 更多