将任何正整数转换为RGB值的算法

Ric*_*ard 21 algorithm rgb

我们有一个想要显示的热图.构成显示值的数字是未知的(除了它们是正整数).数字的范围也是未知的(再次,除了它们将是正整数).范围可以介于0到200或578和1M之间.这取决于数据,这是未知的.

我们想要获取未知范围的正整数并将其转换为缩放(压缩)范围,以在热图中使用RGB值显示.我希望这是有道理的.谢谢!

我想澄清一下min/max值需要"插入"论坛.

Chr*_*s H 21

您需要首先找到这些值的范围以获得最小值和最大值.然后,您需要创建一个颜色比例,如此图像下方的条形图.您可以尝试使用不同的函数将整数映射到RGB.你需要3个函数R(X),G(X),B(X).看下面的图像,中间有B(X)峰,末端有R(X)峰,绿色在其他地方.只要您确保从未获得某个X值的两个(RGB),那么您就可以获得转换.

替代文字http://www.globalwarmingart.com/images/a/aa/Annual_Average_Temperature_Map.jpg

编辑:想想你可以在YUV空间周围采样一些单位圆. 替代文字http://www.biocrawler.com/w/images/e/ec/Yuv.png

或者甚至只需下载高分辨率彩条并对其进行采样.

编辑2:我刚刚面对色条生成并记住了MATLAB/Octave色条代码.我绘制了他们的数据并获得了以下图像. 替代文字


Ian*_*oyd 11

您希望将数据值转换为光照频率:

  • 较低的波长=较冷的颜色=蓝色
  • 更高的波长=更暖的颜色=更红

可见光的频率从大约350nm(紫色)到650nm(红色):

替代文字http://www.gamonline.com/new/catalog/colortheory/images/spectrum.gif

以下函数将指定范围内的数字转换为可见光范围,然后获取rgb:

function DataPointToColor(Value, MinValue, MaxValue: Real): TColor;
var
   r, g, b: Byte;
   WaveLength: Real;
begin
   WaveLength := GetWaveLengthFromDataPoint(Value, MinValue, MaxValue);
   WavelengthToRGB(Wavelength, r, g, b);
   Result := RGB(r, g, b);
end;
Run Code Online (Sandbox Code Playgroud)

有了这个功能,我写下了我的头脑:

function GetWaveLengthFromDataPoint(Value: Real; MinValues, MaxValues: Real): Real;
const
   MinVisibleWaveLength = 350.0;
   MaxVisibleWaveLength = 650.0;
begin
   //Convert data value in the range of MinValues..MaxValues to the 
   //range 350..650

   Result := (Value - MinValue) / (MaxValues-MinValues) *
         (MaxVisibleWavelength - MinVisibleWavelength) +
         MinVisibleWaveLength;
end;
Run Code Online (Sandbox Code Playgroud)

我在互联网上找到的一个功能,将波长转换为RGB:

PROCEDURE WavelengthToRGB(CONST Wavelength:  Nanometers;
                          VAR R,G,B:  BYTE);
  CONST
    Gamma        =   0.80;
    IntensityMax = 255;
  VAR
    Blue   :  DOUBLE;
    factor :  DOUBLE;
    Green  :  DOUBLE;
    Red    :  DOUBLE;
  FUNCTION Adjust(CONST Color, Factor:  DOUBLE):  INTEGER;
  BEGIN
    IF   Color = 0.0
    THEN RESULT := 0     // Don't want 0^x = 1 for x <> 0
    ELSE RESULT := ROUND(IntensityMax * Power(Color * Factor, Gamma))
  END {Adjust};
BEGIN
  CASE TRUNC(Wavelength) OF
    380..439:
      BEGIN
        Red   := -(Wavelength - 440) / (440 - 380);
        Green := 0.0;
        Blue  := 1.0
      END;
    440..489:
      BEGIN
        Red   := 0.0;
        Green := (Wavelength - 440) / (490 - 440);
        Blue  := 1.0
      END;
    490..509:
      BEGIN
        Red   := 0.0;
        Green := 1.0;
        Blue  := -(Wavelength - 510) / (510 - 490)
      END;
    510..579:
      BEGIN
        Red   := (Wavelength - 510) / (580 - 510);
        Green := 1.0;
        Blue  := 0.0
      END;
    580..644:
      BEGIN
        Red   := 1.0;
        Green := -(Wavelength - 645) / (645 - 580);
        Blue  := 0.0
      END;
    645..780:
      BEGIN
        Red   := 1.0;
        Green := 0.0;
        Blue  := 0.0
      END;
    ELSE
      Red   := 0.0;
      Green := 0.0;
      Blue  := 0.0
  END;
  // Let the intensity fall off near the vision limits
  CASE TRUNC(Wavelength) OF
    380..419:  factor := 0.3 + 0.7*(Wavelength - 380) / (420 - 380);
    420..700:  factor := 1.0;
    701..780:  factor := 0.3 + 0.7*(780 - Wavelength) / (780 - 700)
    ELSE       factor := 0.0
  END;
  R := Adjust(Red,   Factor);
  G := Adjust(Green, Factor);
  B := Adjust(Blue,  Factor)
END {WavelengthToRGB}; 
Run Code Online (Sandbox Code Playgroud)

样品用途:

数据集范围为10..65,000,000.此特定数据点的值为638,328:

color = DataPointToColor(638328, 10, 65000000);
Run Code Online (Sandbox Code Playgroud)

  • @Richard:你必须决定什么是不平衡的.例如,如果整个世界都处于深度冻结状态,除了安哥拉的一个城镇,这个城镇太热而无法居住:那么一切*应该是蓝色的,除了那个应该是红色的点.除非您想要在较低范围内夸大**值.您将不得不决定要执行哪种谎言,以便最好地表示您的数据.如果源数据不是线性的(如您所建议的那样),那么常见的技巧是使用对数比例; 在绘制它们之前将自然对数ln(值)应用于值. (5认同)

wil*_*ell 7

colorbar的功能

// value between 0 and 1 (percent)   
function color(value) {
    var RGB = {R:0,G:0,B:0};

    // y = mx + b
    // m = 4
    // x = value
    // y = RGB._
    if (0 <= value && value <= 1/8) {
        RGB.R = 0;
        RGB.G = 0;
        RGB.B = 4*value + .5; // .5 - 1 // b = 1/2
    } else if (1/8 < value && value <= 3/8) {
        RGB.R = 0;
        RGB.G = 4*value - .5; // 0 - 1 // b = - 1/2
        RGB.B = 1; // small fix
    } else if (3/8 < value && value <= 5/8) {
        RGB.R = 4*value - 1.5; // 0 - 1 // b = - 3/2
        RGB.G = 1;
        RGB.B = -4*value + 2.5; // 1 - 0 // b = 5/2
    } else if (5/8 < value && value <= 7/8) {
        RGB.R = 1;
        RGB.G = -4*value + 3.5; // 1 - 0 // b = 7/2
        RGB.B = 0;
    } else if (7/8 < value && value <= 1) {
        RGB.R = -4*value + 4.5; // 1 - .5 // b = 9/2
        RGB.G = 0;
        RGB.B = 0;
    } else {    // should never happen - value > 1
        RGB.R = .5;
        RGB.G = 0;
        RGB.B = 0;
    }

    // scale for hex conversion
    RGB.R *= 15;
    RGB.G *= 15;
    RGB.B *= 15;

    return Math.round(RGB.R).toString(16)+''+Math.round(RGB.G).toString(16)+''+Math.round(RGB.B).toString(16);
}
Run Code Online (Sandbox Code Playgroud)