2010-03-29 29 views
1

J'ai rencontré this ActionScript sample, qui illustre le dessin du spectre de couleurs, une ligne à la fois via une boucle, en utilisant des formes d'onde. Cependant, l'emplacement de la forme d'onde de chaque canal RVB crée un spectre de couleurs qui manque de couleurs (jaune pur, cyan et magenta) et, par conséquent, le spectre est incomplet.Dessin de spectre de couleurs avec forme d'onde

comment puis-je remédier à ce problème afin que le spectre de couleurs dessinées présente toutes les couleurs?

// Loop through all of the pixels from '0' to the specified width. 
for(var i:int = 0; i < nWidth; i++) 
    { 
    // Calculate the color percentage based on the current pixel. 
    nColorPercent = i/nWidth; 

    // Calculate the radians of the angle to use for rotating color values. 
    nRadians = (-360 * nColorPercent) * (Math.PI/180); 

    // Calculate the RGB channels based on the angle. 
    nR = Math.cos(nRadians)     * 127 + 128 << 16; 
    nG = Math.cos(nRadians + 2 * Math.PI/3) * 127 + 128 << 8; 
    nB = Math.cos(nRadians + 4 * Math.PI/3) * 127 + 128; 

    // OR the individual color channels together. 
    nColor = nR | nG | nB; 
    } 

MISE À JOUR SOLUTION


pour toute personne intéressée, voici la solution que j'ai écrit pour résoudre le problème ci-dessus. Les formes d'onde RVB ne sont pas utilisées pour créer le spectre de couleurs complet. De plus, le code est flexible, ce qui vous permet d'attribuer vos propres variables de taille et de couleur à l'image-objet produite. les variables de couleur dans cet exemple sont rouge, jaune, vert, cyan, bleu, magenta, rouge pour produire le spectre complet des couleurs

/* 
//SpectrumGradient Object Call 

var spectrum:SpectrumGradient = new SpectrumGradient(stage.stageWidth, stage.stageHeight, 0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000); 
this.addChild(spectrum); 
*/ 


package 
{ 
    import flash.display.BitmapData; 
    import flash.display.CapsStyle; 
    import flash.display.GradientType; 
    import flash.display.LineScaleMode; 
    import flash.display.Sprite; 
    import flash.geom.Matrix; 

    public class SpectrumGradient extends Sprite 
     { 
     public function SpectrumGradient(spriteWidth:Number, spriteHeight:Number, ...spriteColors) 
      { 
      //Setup spectrum sprite 
      var spectrum:Sprite = new Sprite(); 
      var spectrumAlphas:Array = new Array(); 
      var spectrumRatios:Array = new Array(); 
      var spectrumPartition:Number = 255/(spriteColors.length - 1); 

      for (var pushLoop:int = 0; pushLoop < spriteColors.length; pushLoop++) 
       { 
       spectrumAlphas.push(1); 
       spectrumRatios.push(pushLoop * spectrumPartition); 
       } 

      //Create spectrum sprite as evenly distributed linear gradient using supplied spriteColors 
      var spectrumMatrix:Matrix = new Matrix(); 
      spectrumMatrix.createGradientBox(spriteWidth, spriteHeight); 
      spectrum.graphics.lineStyle(); 
      spectrum.graphics.beginGradientFill(GradientType.LINEAR, spriteColors, spectrumAlphas, spectrumRatios, spectrumMatrix); 
      spectrum.graphics.drawRect(0, 0, spriteWidth, 1); 
      spectrum.graphics.endFill(); 

      //Assign bitmapData to the spectrum sprite 
      var bitmapData:BitmapData = new BitmapData(spectrum.width, spectrum.height, true, 0); 
      bitmapData.draw(spectrum); 

      var pixelColor:Number; 

      for (var i:int = 0; i < spriteWidth; i++) 
       { 
       //Retrieve the color number for each pixel of the spectrum sprite 
       pixelColor = bitmapData.getPixel(i, 0); 

       //Create new matrices for the white and black gradient lines 
       var matrixWhite:Matrix = new Matrix(); 
       matrixWhite.createGradientBox(1, spriteHeight/2, Math.PI * 0.5, 0, 0); 
       var matrixBlack = new Matrix(); 
       matrixBlack.createGradientBox(1, spriteHeight/2, Math.PI * 0.5, 0, spriteHeight/2); 

       //Each slice of the sprite is composed of two vertical lines: the first fades from white to the pixelColor, the second fades from pixelColor to black 
       graphics.lineStyle(1, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE); 
       graphics.lineGradientStyle(GradientType.LINEAR, [0xFFFFFF, pixelColor], [100, 100], [0, 255], matrixWhite); 
       graphics.moveTo(i, 0); 
       graphics.lineTo(i, spriteHeight/2); 
       graphics.lineGradientStyle(GradientType.LINEAR, [pixelColor, 0], [100, 100], [0, 255], matrixBlack); 
       graphics.moveTo(i, spriteHeight/2); 
       graphics.lineTo(i, spriteHeight); 
       } 

      } 
     } 
} 

Répondre

4

vous ne pouvez pas avoir toutes les couleurs à la fois. Toutes les couleurs RVB, c'est 256 x 256 x 256, donc vous auriez besoin de 4096 x 4096 pixels pour les afficher tous.

De plus, il n'y a pas de manière "naturelle"/sensée de les afficher tous. Au moins jusqu'à présent, personne n'a trouvé un espace colorimétrique bidimensionnel qui ait vraiment du sens. Pour afficher les couleurs, vous devez toujours choisir 2. C'est pourquoi les sélecteurs de couleurs communs utilisent soit un hue slider and a lightness/saturation plane ou un hue/saturation plane and a lightness slider.

Veuillez également noter que le premier spectre (rectangulaire) peut être facilement tracé avec 2 gradients superposés. un horizontal pour la teinte, et un vertical (semi-transparent) pour la légèreté. c'est plus rapide et complètement lisse (si vous zoomez, vous ne voyez pas les lignes individuelles).

modifier: est ici un exemple concret de la façon dont cela peut être réalisé avec un seul gradient, ce qui est préférable pour des raisons évidentes:

package { 
    import flash.display.*; 
    import flash.events.Event; 
    import flash.events.MouseEvent; 
    import flash.geom.Matrix; 

    public class GradientTest extends Sprite { 

     public function GradientTest() { 
      var colors:Array = [0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000]; 
      var part:Number = 0xFF/(colors.length-1); 
      var ratios:Array = [], alphas:Array = []; 
      var m:Matrix = new Matrix(); 
      m.createGradientBox(500, 20); 
      for (var i:int = 0; i < colors.length; i++) { 
       ratios.push(part * i); 
       alphas.push(100); 
      } 

      this.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, m); 
      this.graphics.drawRect(0, 0, 500, 20); 

      //just to get the RGB values under the mouse: 
      var b:BitmapData = new BitmapData(this.width, this.height, true, 0); 
      b.draw(this); 
      stage.addEventListener(MouseEvent.MOUSE_MOVE, function (e:Event):void { 
       if (hitTestPoint(mouseX, mouseY)) { 
        var s:String = b.getPixel(mouseX, mouseY).toString(16); 
        while (s.length < 6) s = "0" + s; 
        trace("#" + s);     
       } 
      }); 
     } 
    } 
} 

l'approche en utilisant des formes d'ondes est un peu comme un marteau à la recherche de un ongle. ce n'est pas parce que les opérations sur les bits et la trigonométrie sont d'excellents outils que vous devriez les préférer à une solution beaucoup plus simple.

+1

bien sûr, je ne cherchais pas vraiment à afficher chaque couleur de 16,7 millions dans mon rect, mais plutôt (similaire à votre image ci-jointe pour le plan de teinte/saturation et un curseur de luminosité) répartis uniformément entre les 6 couleurs (rouge, jaune, vert, cyan, bleu, magenta) en utilisant une forme de boucle et d'onde. – TheDarkIn1978

+0

@ TheDarkIn1978 - post mis à jour. – back2dos

+0

merci beaucoup back2dos. :) – TheDarkIn1978