Pintame un arcoiris
-
06-07-2019 - |
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.
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.
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>