Pregunta

¿Cómo harías para hacer un rango de colores RGB espaciados uniformemente sobre el rango de color espectral? Para que parezca un arcoíris real.

¿Fue útil?

Solución

Utilice HSL en su lugar: arregle el brillo y la saturación y varíe el tono de 0 a 360, luego conviértalo a RGB.

HSL describe los colores tal como los percibe la gente. RGB los describe como los usan las máquinas. Por lo tanto, no puede hacer nada visualmente agradable directamente con RGB.

Otros consejos

Puede usar el espacio de color HSV y caminar a través de la dimensión Hue.

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 volver a rojo

Esto debería obtener casi el mismo resultado que barrer los valores de tono en HSV o HSL, pero le permite trabajar directamente en RGB. Tenga en cuenta que solo un componente cambia para cada interpolación, lo que simplifica las cosas. Aquí hay 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
  • Rojo (color web) (Hex: # FF0000) (RGB: 255, 0, 0)
  • Naranja (rueda de colores Naranja) (Hex: # FF7F00) (RGB: 255, 127, 0)
  • Amarillo (color web) (Hex: # FFFF00) (RGB: 255, 255, 0)
  • Verde (X11) (Verde eléctrico) (HTML / CSS & # 8220; Lima & # 8221;) (Rueda de color verde) (Hex: # 00FF00) (RGB: 0, 255, 0)
  • Azul (color web) (Hex: # 0000FF) (RGB: 0, 0, 255)
  • Indigo (Indigo eléctrico) (Hex: # 6600FF) (RGB: 102, 0, 255)
  • Violeta (Violeta eléctrica) (Hex: # 8B00FF) (RGB: 139, 0, 255)

Entre cada color, haga una interpolación lineal.

Esta clase lo hará con PHP, le pasará al constructor la cantidad de colores que desea en su arco iris y la propiedad $ secuencia contendrá una matriz de códigos hexadecimales 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;
    }
}

Para probar, por ejemplo:

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

Solo reclamo crédito por empaquetar esto en una clase, la función original se encontró en esta publicación: Comprensión de la fórmula PHP HSV a RGB

Las otras soluciones requieren grandes cantidades de código y ramificaciones condicionales, lo que las hace inadecuadas para las GPU. Recientemente llegué a la siguiente fórmula mágicamente simple en GLSL. Es esencialmente lo 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 de arco iris que corresponde al valor de tono dado en RGB lineal. Para usar en una imagen, convierta a sRGB y luego multiplique por 255.

Aquí hay una versión de 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);
  }
}

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

Sé que es una pregunta bastante antigua, pero aquí está mi solución simple y fácil de entender, que debería ser fácil de usar en la mayoría de los lenguajes de programación. Reemplace los pasos y whichStep con sus 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;
}

Puedo dibujar un arco iris programáticamente con JavaScript y HTML5.

Ejemplo de RainbowVis-JS con arco iris

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 gradiente utilizando mi biblioteca RainbowVis-JS (que solo encadena los gradientes juntos). Dibujo el arco shape 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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top