Domanda

Come faresti a creare una gamma di colori RGB uniformemente distanziati sulla gamma di colori spettrali? Per sembrare un vero arcobaleno.

È stato utile?

Soluzione

Usa invece HSL: correggi la luminosità e la saturazione e varia la tonalità da 0 a 360, quindi converti in RGB.

HSL descrive i colori come sono percepiti dalle persone. RGB li descrive come vengono utilizzati dalle macchine. Quindi non puoi davvero fare nulla di piacevole visivamente direttamente usando RGB.

Altri suggerimenti

Puoi utilizzare spazio colore HSV e camminare attraverso la dimensione Tonalità.

L'approccio più semplice è fare un'interpolazione lineare (in RGB) tra ogni coppia consecutiva in questa sequenza:

  • # ff0000 rosso
  • # ffff00 giallo
  • # 00ff00 verde
  • # 00ffff ciano
  • # 0000ff blu
  • # ff00ff magenta
  • # ff0000 torna al rosso

Questo dovrebbe ottenere praticamente lo stesso risultato della scansione dei valori di tonalità in HSV o HSL, ma ti consente di lavorare direttamente in RGB. Si noti che solo un componente cambia per ogni interpolazione, il che semplifica le cose. Ecco un'implementazione di 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
  • Rosso (colore web) (esadecimale: # FF0000) (RGB: 255, 0, 0)
  • Arancione (ruota dei colori arancione) (esadecimale: # FF7F00) (RGB: 255, 127, 0)
  • Giallo (colore web) (esadecimale: # FFFF00) (RGB: 255, 255, 0)
  • Verde (X11) (Verde elettrico) (HTML / CSS “Lime”) (Ruota dei colori verde) (Hex: # 00FF00) (RGB: 0, 255, 0)
  • Blu (colore web) (esadecimale: # 0000FF) (RGB: 0, 0, 255)
  • Indigo (Electric Indigo) (Hex: # 6600FF) (RGB: 102, 0, 255)
  • Violet (Electric Violet) (Hex: # 8B00FF) (RGB: 139, 0, 255)

Tra ogni colore crea interpolazione lineare.

Questa classe lo farà con PHP, passerà al costruttore il numero di colori desiderato nel tuo arcobaleno e la proprietà $ sequence conterrà una matrice di codici esadecimali 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;
    }
}

Per testare ad es .:

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

Chiedo solo credito per averlo impacchettato in una classe, la funzione originale è stata trovata in questo post: Comprensione della formula da PHP HSV a RGB

Le altre soluzioni richiedono quantità piuttosto elevate di codice e diramazioni condizionate, il che le rende inadatte alle GPU. Di recente sono arrivato alla seguente formula magicamente semplice in GLSL. È essenzialmente lo stesso in 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);
}

Questo ti darà un colore arcobaleno che corrisponde al valore di tonalità dato in RGB lineare. Per utilizzarlo in un'immagine, converti in sRGB e quindi moltiplica per 255.

Ecco una versione 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 chiave qui è rendersi conto che il grafico di ciascuna delle coordinate R, G, B in funzione del valore della tonalità è un valore bloccato di una funzione triangolare periodica e che può essere ottenuto come valore assoluto di un dente di sega funzione, x - floor (x) .

So che è una domanda piuttosto vecchia, ma ecco la mia soluzione semplice e di facile comprensione, che dovrebbe essere facile da usare nella maggior parte dei linguaggi di programmazione. Sostituisci i passaggi e whoStep con i tuoi valori.

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

Posso disegnare un arcobaleno a livello di codice con JavaScript e HTML5.

Esempio RainbowVis-JS con arco arcobaleno

Faccio un gradiente da rgb (255,0,0) - > rgb (255.255,0) - > rgb (0,255,0) - > rgb (0,255,255) - > rgb (0,0.255) - > rgb (255,0,255).

Calcolo i valori del colore esadecimale lungo il gradiente usando la mia libreria RainbowVis-JS (che solo catene gradienti insieme). Traccio l'arco forma con HTML5 Canvas, scorrendo tra i colori.

<!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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top