【问题标题】:Drawing Color Spectrum with Waveform用波形绘制色谱
【发布时间】:2010-03-29 06:59:48
【问题描述】:

我遇到过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);
                }

            }
        }
}

【问题讨论】:

    标签: actionscript-3 colors drawing waveform spectrum


    【解决方案1】:

    你不能同时拥有所有颜色。所有 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);                 
                    }
                });
            }   
        }
    }
    

    使用波形的方法有点像寻找钉子的锤子。仅仅因为位运算和三角函数是很好的工具,并不意味着您应该更喜欢它们而不是更简单的解决方案。

    【讨论】:

    • 当然,我并不是真的希望在我的矩形中显示 1670 万种颜色,而是(类似于您为色相/饱和度平面和亮度滑块附加的图像)均匀分布的颜色使用循环和波形在 6 种主要颜色(红色、黄色、绿色、青色、蓝色、洋红色)之间渐变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2011-06-29
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多