2009-07-31 12 views
23

¿Cómo harías para hacer una gama de colores RGB espaciados uniformemente sobre el rango de color espectral? Para parecerse a un arcoiris real.Píntame un arco iris

Respuesta

16

Use HSL en su lugar: corrija el brillo y la saturación y cambie el tono de 0 a 360, luego conviértalo a RGB.

HSL describe los colores según los percibe la gente. RGB los describe como los usan las máquinas. Por lo tanto, no se puede hacer nada agradable visualmente utilizando RGB.

1
  • rojo (color web) (Hex: # FF0000) (RGB: 255, 0, 0)
  • Orange (rueda de color naranja) (Hex: # FF7F00) (RGB: 255 , 127, 0)
  • amarillo (color web) (Hex: # FFFF00) (RGB: 255, 255, 0)
  • verde (X11) (verde eléctrico) (/ CSS “cal”) (rueda de colores HTML verde) (Hexágono: # 00FF00) (RGB: 0, 255, 0)
  • Azul (color de la red) (Hex: # 0000FF) (RGB: 0, 0, 255)
  • Indigo (Electric Indigo) (Hex: # 6600FF) (RGB: 102, 0, 255)
  • Violet (Electric Violet) (Hex: # 8B00FF) (RGB: 139, 0, 255)

Entre cada color realice una interpolación lineal.

+0

interpolación lineal en qué espacio de color? ;) –

+0

En RGB, por supuesto. Puede tomar estos puntos para las interpolaciones lineales # FF0000 # FFFF00 # 00FF00 # 00FFFF # 0000FF # FF00FF # FF0000, en ese caso se vería como menos natural. Tomé intepolaciones de colores "arco iris" al hacer luces de cristal RGB de lujo –

+0

¿No es mejor terminar con violeta intenso en lugar de violeta eléctrico? – Annan

7

El enfoque más simple es hacer una interpolación lineal (en RGB) entre cada par consecutivo en esta secuencia:

  • #ff0000 rojo
  • #ffff00 amarillo
  • #00ff00 verde
  • #00ffff cian
  • #0000ff azul
  • #ff00ff magenta
  • #ff0000 vuelta a rojo

Esto debe conseguir que más o menos el mismo resultado que el barrido a través de los valores de tono en VHS o HSL, pero le permite trabajar directamente en el RGB. Tenga en cuenta que solo un componente cambia para cada interpolación, lo que simplifica las cosas. He aquí una implementación de 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 
+0

Un pequeño problema es que el arco iris termina en violeta, no en rojo. – Annan

+0

Es cierto. Este problema también existe con las soluciones HSL y HSV. –

1

Esta clase lo hará con PHP, pasar al constructor el número de colores que desee en su arco iris y la propiedad de secuencia $ contendrá una serie de códigos rrggbb hexagonales.

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; 
    } 
} 

Para probar, p.:

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

sólo reclamar el crédito para el envasado de esto en una clase, la función original fue encontrado en este post: PHP HSV to RGB formula comprehension

-1

puedo dibujar un arco iris mediante programación con JavaScript y HTML5.

RainbowVis-JS example with rainbow arc

hago un gradiente de rgb (255,0,0) -> rgb (255,255,0) -> RGB (0,255,0) -> rgb (0,255,255) -> rgb (0, 0,255) -> rgb (255,0,255).

Calculo los valores de color hexadecimal a lo largo del degradado usando mi biblioteca RainbowVis-JS (que simplemente encadena los degradados). Dibujo el arco forma con HTML5 Canvas, recorriendo los colores.

<!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

Sé que es bastante vieja pregunta, pero aquí es mi simple y fácil de entender solución, que debe ser fácil de usar en la mayoría de los lenguajes de programación. Reemplaza los pasos y sigue avanzando con tus propios valores.

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

Las otras soluciones requieren cantidades bastante grandes de código y bifurcación condicional, lo que los hace inadecuados para las GPU. Recientemente llegué a la siguiente fórmula mágicamente simple en GLSL. Es esencialmente el mismo en 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); 
} 

Esto le dará un color del arco iris que corresponde al valor de tono dado en RGB lineal. Para usar en una imagen, convertir a sRGB y luego se multiplica por 255.

Aquí es un C++ versión:

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); 
    } 
} 

La clave aquí es darse cuenta de que la gráfica de cada una de las R, G, B las coordenadas en función del valor de matiz son un valor fijo de una función de triángulo periódico, y se pueden obtener como el valor absoluto de una función de diente de sierra, x - floor(x).

Cuestiones relacionadas