Peins-moi un arc en ciel
-
06-07-2019 - |
Question
Comment feriez-vous pour créer une gamme de couleurs RVB uniformément répartie sur la gamme de couleurs spectrale? Pour ressembler à un véritable arc-en-ciel.
La solution
Utilisez plutôt HSL: réglez la luminosité et la saturation et faites varier la teinte de 0 à 360, puis convertissez-le en RVB.
HSL décrit les couleurs telles qu'elles sont perçues par les gens. RVB les décrit comme ils sont utilisés par les machines. Vous ne pouvez donc rien faire qui soit visuellement agréable en utilisant directement RVB.
Autres conseils
Vous pouvez utiliser l’ espace colorimétrique HSV et parcourir la dimension Hue.
L’approche la plus simple consiste à effectuer une interpolation linéaire (en RVB) entre chaque paire consécutive de cette séquence:
-
# ff0000
rouge -
# ffff00
jaune -
# 00ff00
vert -
# 00ffff
cyan -
# 0000ff
bleu -
# ff00ff
magenta ??li> -
# ff0000
retour au rouge
Cela devrait vous donner à peu près le même résultat que de parcourir les valeurs de teinte dans HSV ou HSL, mais vous permet de travailler directement en RVB. Notez que seul un composant change pour chaque interpolation, ce qui simplifie les choses. Voici une implémentation 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
- Rouge (couleur Web) (Hex: # FF0000) (RVB: 255, 0, 0)
- Orange (roue de couleur orange) (Hex: # FF7F00) (RVB: 255, 127, 0)
- Jaune (couleur Web) (Hex: # FFFF00) (RVB: 255, 255, 0)
- Vert (X11) (Vert électrique) (HTML / CSS “Chaux”) (Roue de couleurs verte) (Hex: # 00FF00) (RGB: 0, 255, 0)
- Bleu (couleur Web) (Hex: # 0000FF) (RGB: 0, 0, 255)
- Indigo (Indigo électrique) (Hex: # 6600FF) (RGB: 102, 0, 255)
- Violet (Violet électrique) (Hex: # 8B00FF) (RGB: 139, 0, 255)
Entre chaque couleur, effectuer une interpolation linéaire.
Cette classe le fera avec PHP, transmettra au constructeur le nombre de couleurs que vous souhaitez dans votre arc-en-ciel et la propriété $ sequence contiendra un tableau de codes hexadécimaux 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;
}
}
Pour tester, par exemple:
$c = new color(100);
foreach($c->sequence as $col)
print "<div style='background-color:#$col'>$col</div>\n";
Je ne réclame de crédit que pour l’emballage de cette classe, la fonction originale a été trouvée dans cet article: Compréhension des formules PHP HSV à RGB
Les autres solutions nécessitent des quantités de code et des branches conditionnelles assez importantes, ce qui les rend inadaptées aux GPU. Je suis récemment arrivé à la formule simple comme par magie suivante dans GLSL. C'est essentiellement la même chose dans 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);
}
Cela vous donnera une couleur arc-en-ciel qui correspond à la valeur de teinte donnée en RVB linéaire. Pour l’utiliser dans une image, convertissez-le en sRGB, puis multipliez-le par 255.
Voici une version 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 clé ici est de réaliser que le graphe de chacune des coordonnées R, V, B en fonction de la valeur de teinte est une valeur pincée d'une fonction de triangle périodique, et que l'on peut l'obtenir comme valeur absolue d'une dent de scie. fonction, x - sol (x)
.
Je sais que la question est plutôt ancienne, mais voici ma solution simple et facile à comprendre, qui devrait être facile à utiliser dans la plupart des langages de programmation. Remplacez les étapes et whichStep par vos propres valeurs.
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;
}
Je peux dessiner un arc-en-ciel par programmation avec JavaScript et HTML5.
Je crée un dégradé à partir de rgb (255,0,0) - > rgb (255,255,0) - > rgb (0,255,0) - > rgb (0,255,255) - > rgb (0,0255) - > rgb (255,0,255).
Je calcule les valeurs de couleur hexadécimales le long du dégradé à l'aide de ma bibliothèque RainbowVis-JS (qui enchaîne simplement les dégradés). Je dessine l'arc forme avec HTML5 Canvas, en passant en revue les couleurs.
<!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>