2009-07-31 69 views
23

你会如何在光谱色彩范围内均匀分布一系列RGB颜色?看起来像一个真正的彩虹。给我一个彩虹

回答

16

使用HSL代替:固定亮度和饱和度,并将色调从0变为360,然后转换为RGB。

HSL描述人们感知的颜色。 RGB将它们描述为由机器使用。所以你不能直接使用RGB来做视觉上令人愉快的事情。

1
  • 红色(Web颜色)(十六进制:#FF0000)(RGB:255,0,0)
  • 橙色(色轮橙色)(己烷:#FF7F00)(RGB:255 ,127,0)
  • 黄色(网络颜色)(Hex:#FFFF00)(RGB:255,255,0)
  • 绿色(X11)(电绿色)(HTML/CSS“酸橙”)(色轮绿色)(Hex:#00FF00)(RGB:0,255,0)
  • 蓝色(网络颜色)(十六进制:#0000FF)(RGB:0,0,255)
  • 靛蓝(电动靛蓝)(十六进制:#6600FF)(RGB:102,0,255)
  • 紫(电气紫)(十六进制:#8B00FF)(RGB:139,0,255)

在每种颜色之间进行线性插值。

+0

其中彩色空间的线性插值? ;) – 2009-07-31 10:15:18

+0

当然在RGB。在这种情况下,您可能会将这些点用于线性插值#FF0000#FFFF00#00FF00#00FFFF#0000FF#FF00FF#FF0000看起来不那么自然。在制作花哨的RGB玻璃灯时,我采用了“彩虹”色互换 – 2009-07-31 10:38:31

7

最简单的方法是做每个连续对之间的线性插值(在RGB)此序列:

  • #ff0000红色
  • #ffff00黄色
  • #00ff00绿色
  • #00ffff青色
  • #0000ff蓝色
  • #ff00ff品红
  • #ff0000回冲

这应该让你几乎相同的结果,通过HSV或HSL的色调值扫地,但可让您直接在RGB工作。请注意,每次插值只有一个组件发生变化,这可以简化事情。这里有一个Python实现:

def rainbow(): 
    r, g, b = 255, 0, 0 
    for g in range(256): 
    yield r, g, b 
    for r in range(255, -1, -1): 
    yield r, g, b 
    for b in range(256): 
    yield r, g, b 
    for g in range(255, -1, -1): 
    yield r, g, b 
    for r in range(256): 
    yield r, g, b 
    for b in range(255, -1, -1): 
    yield r, g, b 
1

本课程将用PHP做,通过构造函数的颜色你在你的彩虹希望和数量$序列属性将包含的RRGGBB十六进制代码数组。

class color 
{ 
    public $sequence = array(); 

    /** 
    * constructor fills $sequence with a list of colours as long as the $count param 
    */ 
    public function __construct($count, $s = .5, $l = .5) 
    { 
     for($h = 0; $h <= .85; $h += .85/$count) //.85 is pretty much in the middle of the violet spectrum 
     { 
      $this->sequence[] = color::hexHSLtoRGB($h, $s, $l); 
     } 
    } 

    /** 
    * from https://stackoverflow.com/questions/3597417/php-hsv-to-rgb-formula-comprehension#3642787 
    */ 
    public static function HSLtoRGB($h, $s, $l) 
    { 

     $r = $l; 
     $g = $l; 
     $b = $l; 
     $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : (l + $s - l * $s); 
     if ($v > 0){ 
       $m; 
       $sv; 
       $sextant; 
       $fract; 
       $vsf; 
       $mid1; 
       $mid2; 

       $m = $l + $l - $v; 
       $sv = ($v - $m)/$v; 
       $h *= 6.0; 
       $sextant = floor($h); 
       $fract = $h - $sextant; 
       $vsf = $v * $sv * $fract; 
       $mid1 = $m + $vsf; 
       $mid2 = $v - $vsf; 

       switch ($sextant) 
       { 
        case 0: 
          $r = $v; 
          $g = $mid1; 
          $b = $m; 
          break; 
        case 1: 
          $r = $mid2; 
          $g = $v; 
          $b = $m; 
          break; 
        case 2: 
          $r = $m; 
          $g = $v; 
          $b = $mid1; 
          break; 
        case 3: 
          $r = $m; 
          $g = $mid2; 
          $b = $v; 
          break; 
        case 4: 
          $r = $mid1; 
          $g = $m; 
          $b = $v; 
          break; 
        case 5: 
          $r = $v; 
          $g = $m; 
          $b = $mid2; 
          break; 
       } 
     } 
     return array('r' => floor($r * 255.0), 
        'g' => floor($g * 255.0), 
        'b' => floor($b * 255.0) 
        ); 
    } 

    //return a hex code from hsv values 
    public static function hexHSLtoRGB($h, $s, $l) 
    { 
     $rgb = self::HSLtoRGB($h, $s, $l); 
     $hex = base_convert($rgb['r'], 10, 16) . base_convert($rgb['g'], 10, 16) . base_convert($rgb['b'], 10, 16); 
     return $hex; 
    } 
} 

为了测试例如:

$c = new color(100); 
foreach($c->sequence as $col) 
    print "<div style='background-color:#$col'>$col</div>\n"; 

我只邀功包装这一成一类,原有的功能在这个帖子中发现: PHP HSV to RGB formula comprehension

-1

我可以通过编程画彩虹JavaScript和HTML5。

RainbowVis-JS example with rainbow arc

我使从RGB(255,0,0)的梯度 - (0255255)> RGB - - > RGB(255,255,0) - > RGB(0,255,0)0> RGB(, 0,255) - > rgb(255,0,255)。

我使用我的RainbowVis-JS库(它只是将梯度链接在一起)计算沿着梯度的十六进制颜色值。 我使用HTML5画布绘制圆形形状,循环显示颜色。

<!DOCTYPE html> 
<html> 
    <head> 
    <script src="rainbowvis.js"></script> 
    </head> 
    <body> 
    <script type="text/javascript"> 
     window.onload = function(){ 

     var RAINBOW_WIDTH = 60; 
     var RAINBOW_RADIUS = 130; 

     // Library class 
     var rainbow = new Rainbow(); 
     rainbow.setNumberRange(1, RAINBOW_WIDTH); 
     rainbow.setSpectrum(
      'FF0000', 'FFFF00', '00FF00', 
      '00FFFF', '0000FF', 'FF00FF' 
     ); 

     // Canvas 
     var canvas = document.getElementById('MyCanvas'); 
     var context = canvas.getContext('2d'); 

     context.lineWidth = 1; 
     for (var i = 1; i <= RAINBOW_WIDTH; i++) { 
      context.beginPath(); 
      context.arc(canvas.width/2, canvas.width/2, RAINBOW_RADIUS - i+1, 
      Math.PI, 0, false); 
      context.strokeStyle = '#' + rainbow.colourAt(i); // Library function 
      context.stroke(); 
     } 
     }; 
    </script> 
    <canvas id="MyCanvas" width="300" height="300"> 
     <p>Rainbow arc example. Your browser doesn't support canvas.</p> 
    </canvas> 
    </body> 
</html> 
0

我知道这是相当古老的问题,但这里是我的简单和易于理解的解决方案,这应该是很容易在大多数编程语言使用。 用您自己的值替换步骤和whichStep。

int steps = 1280; 
int stepChange = 1280/steps; 
int change = stepChange * whichStep; 
int r=0, g=0, b=0; 

if (change < 256) 
{ 
    r = 255; 
    g += change; 
} 
else if (change < 512) 
{ 
    r = 511 - change; 
    g = 255; 
} 
else if (change < 768) 
{ 
    g = 255; 
    b = change-512; 
} 
else if (change < 1024) 
{ 
    g = 1023 - change; 
    b = 255; 
} 
else 
{ 
    r = change - 1024; 
    b = 255; 
} 
0

其他解决方案需要相当大量的代码和条件分支,这使得它们不适合GPU。我最近在GLSL中得到了以下神奇简单的公式。它在OpenCL中基本相同:

vec3 HueToRGB(float hue) { 
    vec3 h = vec3(hue, hue + 1.0/3.0, hue + 2.0/3.0); 
    return clamp(6.0 * abs(h - floor(h) - 0.5) - 1.0, 0.0, 1.0); 
} 

这会给你一个彩虹色,它对应于线性RGB中给定的色调值。到的图像中使用,则转换为sRGB和然后乘以255

这里是一个C++版本:

float clamp(float value, float low, float high) { 
    return value < low ? low : (value > high ? high : value); 
} 
void HueToRGB(float hue, float *rgb) { 
    rgb[0] = hue; 
    rgb[1] = hue + 1.f/3.f; 
    rgb[2] = hue + 2.f/3.f; 
    for (unsigned i = 0; i < 3; ++i) { 
    rgb[i] = clamp(6.0f * fabsf(rgb[i] - floorf(rgb[i]) - 0.5f) - 1.f, 0.f, 1.f); 
    } 
} 

这里的关键是认识到,每个R,G,B的图色调值函数中的坐标是周期性三角函数的钳位值,并且可以作为锯齿函数的绝对值获得,x - floor(x)