2009-07-31 66 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)