【问题标题】:Color Mapping For Specific Range特定范围的颜色映射
【发布时间】:2017-11-03 17:41:49
【问题描述】:

我有一个小问题,我正在尝试绘制不同的颜色点,颜色必须取决于与最大范围和最小范围内的点关联的某个值。我希望在红色 - 黄色 - 绿色之间进行颜色缩放。

现在,我将红色与最大值相关联,而绿色与最小值相关联。对于所有其他中间点,我想从绿色到黄色再到红色,这个问题我不知道如何设置所有东西都变成黄色,因为现在我只能通过绿色和红色渐变。

代码:

red = (int) (value * (255));
green = 255 - red;
blue = 0 ;

Color color = new Color((int) red, (int) green, (int) blue);
String hex = Integer.toHexString(color.getRGB() & 0xffffff);

范围从 1 (MAX) 到 0 (MIN),因此值在 [0,1] 范围内。

我怎样才能修复所有问题以获得黄色渐变?

【问题讨论】:

    标签: java colors color-scheme


    【解决方案1】:

    使用 HSB 模型而不是 RGB。在 HSB 中,您只需要指定所需颜色的角度。 Color#getHSBColor(float h, float s, float b);Here你可以尝试混合HSB(HSV)颜色。

    这是一个示例,如何在指定的颜色间隔中创建 n 种不同的颜色:

    public static Color[] intervalColors(float angleFrom, float angleTo, int n) {
        float angleRange = angleTo - angleFrom;
        float stepAngle = angleRange / n;
    
        Color[] colors = new Color[n];
        for (int i = 0; i < n; i++) {
            float angle = angleFrom + i*stepAngle;
            colors[i] = Color.getHSBColor(angle, 1.0, 1.0);        
        }
        return colors;
    }
    ...
        Color[] colors = intervalColors(0, 120, 10); // red to green
        Arrays.sort(colors, Comparator.reversed()); // green to red
    

    将颜色映射到 范围内的值:

    /**
     * Remaps x from old-interval to new-interval.
     * DoubleInterval just wraps double values a, b.
     */
    public static double remap(double x, DoubleInterval oldDomain, DoubleInterval newDomain) {
        double oldRange = oldDomain.size(); // oldDomain.b - oldDomain.a
        double oldRangeValue = x - oldDomain.a; // lowerBound a is just an offset
        double percentile = oldRangeValue / oldRange;
    
        double newRange = newDomain.size(); // newDomain.b - newDomain.a
        double newRangeValue = percentile * newRange;
        double newVal = newRangeValue + newDomain.a;
        return newVal;
    }
    
    /**
     * Returns color from specified color-interval that matches normValue <0,1>.
     * If normValue = 0, angleFrom = 0 (red), angleTo = 120 (green) then color = red. 
     */
    public static Color intervalColor(float normValue, float angleFrom, float angleTo) {
        double angleValue = remap(normValue, new DoubleInterval(0, 1), new DoubleInterval(angleFrom, angleTo));
        return Color.getHSBColor(angleValue, 1.0, 1.0);        
    }
    
    /**
     * Returns inversion of specified value in given domain.
     * Example: if x = 0.3 and domain of x is <0,1> then inversion = 0.7
     */
    public static double invert(double x, DoubleInterval domain) {
        return (domain.b - x) + domain.a;
    }
    
    /**
     * Returns color from specified color-interval that matches inverted normValue <0,1>.
     * If normValue = 0 and angleFrom = 0 (red) and angleTo = 120 (green) then color = green. 
     */
    public static Color invertedIntervalColor(float normValue, float angleFrom, float angleTo) {
        double invNormValue = invert(normValue, new DoubleInterval(0, 1));
        return intervalColor(invNormValue, angleFrom, angleTo);      
    }
    

    【讨论】:

      【解决方案2】:

      您可以尝试 HSV 色彩空间。通过改变 Hue 组件,您可以按照您想要的方式改变颜色。

      float value = 0; //this is your value between 0 and 1
      float minHue = 120f/255; //corresponds to green
      float maxHue = 0; //corresponds to red
      float hue = value*maxHue + (1-value)*minHue; 
      Color c = new Color(Color.HSBtoRGB(hue, 1, 0.5f));
      

      这会插入最小和最大颜色的色调。如果要在值和饱和度不同的颜色之间进行插值。也可以在这些之间进行插值。

      【讨论】:

      • 我实际上有积分,每个积分都与一个介于 0 和 1 之间的值相关联。当一个积分的值为 1 时,我必须兑换它,如果它有 0,我必须着色它是绿色的,在所有其他情况下,我必须在它们之间进行一次缩放,例如,如果值为 0.5,我必须将其着色为黄色。
      • 我希望我解释得更好。
      • @traveller 看到我更新的答案,这应该适合你。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 2018-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      相关资源
      最近更新 更多