2010-03-29 142 views
1

我遇到了this ActionScript sample,它演示了使用波形通过循环一次绘制一条线的色谱图。但是,每个RGB通道的波形位置会创建缺失颜色(纯黄色,青色和洋红色)的色谱,因此光谱不完整。使用波形绘制色谱图

我该如何解决这个问题,以便绘制的色谱将显示所有的颜色?

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

更新的解决方案


兴趣的人,下面是我写的解决上述问题的解决方案。 RGB波形不用于创建全色光谱。代码也很灵活,因此您可以为生成的精灵分配自己的大小和颜色变量。在这个例子中,颜色变量是红,黄,绿,青,蓝,洋红,红色,产生完整的色彩频谱

/* 
//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); 
       } 

      } 
     } 
} 

回答

4

你不能拥有所有的颜色一次。所有的RGB颜色,这是256 x 256 x 256,所以你需要4096 x 4096像素来显示所有这些。

此外,没有“自然”/明智的方式显示它们。至少到现在为止,没有人提出一个真正有意义的二维色彩空间。为了显示颜色,您必须始终选择2.这就是常用颜色选择器使用hue slider and a lightness/saturation planehue/saturation plane and a lightness slider的原因。

另请注意,第一个(矩形)光谱可以用2个重叠的梯度轻松绘制。一个水平的色调,一个垂直(半透明)的亮度。它的速度更快,并且完全平滑(如果放大,您看不到单独的线条)。

编辑:这里有一个如何这可以用一个单一的渐变,这是优选的原因很明显可以实现一个工作示例:

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

使用波形的方法有点像在搜索的锤钉子。仅仅因为位操作和三角函数是很好的工具,并不意味着你应该更喜欢它们的解决方案,这更简单。

+1

当然,我并不是真的想要在显示器上显示1670万色的每一种颜色,而是(类似于用于色相/饱和度平面和亮度滑块的附加图像)均匀分布在6个主色颜色(红色,黄色,绿色,青色,蓝色,洋红色)使用循环和波形。 – TheDarkIn1978 2010-03-29 08:56:57

+0

@TheDarkIn7878 - 发布更新。 – back2dos 2010-03-29 10:35:30

+0

非常感谢back2dos。 :) – TheDarkIn1978 2010-03-29 12:20:21