【问题标题】:Calculating heat map colours计算热图颜色
【发布时间】:2013-07-23 05:02:11
【问题描述】:

我正在制作由 HTML 表格组成的热图。此表包含 n 个单元格,并具有 最低 值和 最高 值(最高总是高于最低)。每个单元格都有一个 cell 值。所有这些值都是整数。

具有最低值的单元格应为浅蓝色,缩放到具有最高值的单元格为深红色的点。请参阅下面的渐变以获得理想范围:

要计算每个单独单元格的十六进制颜色值,我会查看表格中的 最低最高 值以及单元格的 total值,将它们传递给返回 RGB 十六进制的方法,准备好与 HTML 的 background-color 样式一起使用。

目前的方法如下:

public string ConvertTotalToRgb(int low, int high, int cell)
{
    int range = high - low;

    int main = 255 * cell/ range;
    string hexR = main.ToString("X2");
    int flip = 255 * (1 - (cell/ range));
    string hexB = flip.ToString("X2");

    return hexR + "00" + hexB;
}

最低值为 0,最高值为 235,此方法返回下表(单元格值在单元格中)。

示例:如果 lowest 为 20,highest 为 400,cell 为 60,我希望方法返回 RGB 十六进制颜色大约是渐变的 15.8%。

400 - 20 = 380
380 / 60 = 6.33
100 / 6.33 = 15.8

我知道这个公式不太准确,但这也是我在这里寻求帮助的部分原因。

我已经做到了这一点,但我真的不知道如何继续。非常感谢任何帮助!

【问题讨论】:

  • 你的问题真令人困惑.. HTML表格是什么样的?
  • 我确实在问题的底部放了一张桌子的图片:/
  • 那我误会了..值从何而来?
  • 值的来源应该与这个问题无关;我有目的地将范围缩小到一种方法。这种单一方法接受最低可能值(将呈现为渐变中最左侧的颜色)、最高可能值(将呈现为渐变中最右侧的颜色)以及将呈现为某处颜色的单元格值在渐变中取决于值。
  • 例如,如果最低为 20,最高为 400,单元格为 60,我希望该方法返回颜色的 RGB 十六进制值,沿着渐变的 15% 左右。

标签: c# hex rgb heatmap


【解决方案1】:

今天我用谷歌搜索了一些关于他的问题的帮助,但没有答案我找到了答案。

“热图”不是原始 Value% 到 Hue 的转换,它可以用 7、5 或更少的颜色构建(例如:红色到黄色),可以是线性或对数等。

我编写并分享了一个 C# .Net 4.6.1 代码,它可以作为构建 ValueToColorOnHeatMap 转换器的坚实基础: (注意:这是经过调试和测试的)

using System.Windows.Media;// for WPF
// for WindowsForms using System.Drawing
using System;
using System.Collections.Generic;
public class ColorHeatMap
{
    public ColorHeatMap()
    {
        initColorsBlocks();
    }
    public ColorHeatMap(byte alpha)
    {
        this.Alpha = alpha;
        initColorsBlocks();
    }
    private void initColorsBlocks()
    {
        ColorsOfMap.AddRange(new Color[]{
            Color.FromArgb(Alpha, 0, 0, 0) ,//Black
            Color.FromArgb(Alpha, 0, 0, 0xFF) ,//Blue
            Color.FromArgb(Alpha, 0, 0xFF, 0xFF) ,//Cyan
            Color.FromArgb(Alpha, 0, 0xFF, 0) ,//Green
            Color.FromArgb(Alpha, 0xFF, 0xFF, 0) ,//Yellow
            Color.FromArgb(Alpha, 0xFF, 0, 0) ,//Red
            Color.FromArgb(Alpha, 0xFF, 0xFF, 0xFF) // White
        });
    }
    public Color GetColorForValue(double val, double maxVal)
    {
        double valPerc = val / maxVal;// value%
        double colorPerc = 1d / (ColorsOfMap.Count-1);// % of each block of color. the last is the "100% Color"
        double blockOfColor = valPerc / colorPerc;// the integer part repersents how many block to skip
        int blockIdx = (int)Math.Truncate(blockOfColor);// Idx of 
        double valPercResidual = valPerc - (blockIdx*colorPerc);//remove the part represented of block 
        double percOfColor = valPercResidual / colorPerc;// % of color of this block that will be filled

        Color cTarget = ColorsOfMap[blockIdx];
        Color cNext = cNext = ColorsOfMap[blockIdx + 1]; 

        var deltaR =cNext.R - cTarget.R;
        var deltaG =cNext.G - cTarget.G;
        var deltaB =cNext.B - cTarget.B;

        var R = cTarget.R + (deltaR * percOfColor);
        var G = cTarget.G + (deltaG * percOfColor);
        var B = cTarget.B + (deltaB * percOfColor);

        Color c = ColorsOfMap[0];
        try
        {
            c = Color.FromArgb(Alpha, (byte)R, (byte)G, (byte)B);
        }
        catch (Exception ex)
        {
        }
        return c;
    }
    public byte Alpha = 0xff;
    public List<Color> ColorsOfMap = new List<Color>();
}

要使用更少或个性化的颜色,请使用ColorsOfMap 列表。 该类使用比例、线性、表示,在blocOfColor 上工作以改变线性。

我希望这会帮助一些人节省时间:)

感谢所有与社区分享他们的答案/解决方案的人。

要使用更少或个性化的颜色,请使用ColorsOfMap 列表。 该类使用比例、线性、reperesentation,在blocOfColor 上工作以改变线性度。

我希望这会帮助一些人节省时间:)

感谢所有与社区分享他们的答案/解决方案的人。

【讨论】:

  • 正如所写,当使用 val == maxval 调用 GetColorForValue 时,此代码会因索引越界异常而崩溃。一个简单的解决方法是double valPerc = val / (maxval + 1)
  • 顺便说一句,这是我经过几个小时的搜索后找到的最好的颜色映射代码示例。使用 (maxval + 1) 将 valPerc 保持在 1.0 以下在我的环境中效果很好,但根据值的范围,您可能需要不同的方法。
  • 我也用过这个实现,很好。您可以在渐变等中配置自己的颜色。但是我更改了一些行。您的实现假设 minVal 为 0 但如果不是怎么办?所以我使用了double valPerc = (val-minVal) / (maxVal-minVal); 也改变了@Craig.Feied 对val==maxVal 的处理方式Color cNext = val == maxVal ? ColorGradient[blockIdx] : ColorGradient[blockIdx + 1]; 因为当你使用double valPerc = val / (maxval + 1) 时,你永远不会达到最大颜色,在这种情况下是红色。
  • 我通过将最后一种颜色(白色)两次添加到ColorsOfMap 列表中来修复索引错误,然后在计算colorPerc 时使用ColorsOfMap.Count-2 而不是ColorsOfMap.Count-1
【解决方案2】:

您真正想要的是 HSV 颜色,因为色调(H 值)是周期性的。如果色相介于 0 和 1 之间,则它表示您想要在颜色渐变中走多远。在这种情况下,饱和度和值分量始终为 1。

在此处遵循 HSV 到 RGB 的转换代码: HSV to RGB Stops at yellow C#

public string ConvertTotalToRgb(int low, int high, int cell)
{
    int range = high - low;
    float h= cell/ (float)range;
    rgb = HSVtoRGB(h,1.0f,1.0f);
    return "#" + rgb.R.ToString("X2") + rgb.G.ToString("X2") + rgb.B.ToString("X2");
}

如果你知道你可以定位支持它的浏览器 (CSS3),你可以直接渲染 hsv 值。

【讨论】:

  • 这似乎不起作用 - 它将上表中的所有内容呈现为红色。
  • 好的,我找到了问题所在。色调是一个很小的小数,这意味着它几乎不会沿着光谱移动颜色。当它乘以 240(HSV 光谱上纯蓝色的位置)时,它按预期工作。感谢您的帮助!
猜你喜欢
  • 2012-07-07
  • 1970-01-01
  • 2019-03-08
  • 2016-07-20
  • 2019-07-14
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多