Рисование цветового спектра с помощью формы волны - PullRequest
1 голос
/ 29 марта 2010

я сталкивался с этим примером ActionScript , который демонстрирует рисование цветового спектра, по одной линии за раз через цикл, с использованием сигналов.

однако расположение сигнала каждого канала 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);
                }

            }
        }
}

1 Ответ

4 голосов
/ 29 марта 2010

Вы не можете иметь все цвета одновременно. все цвета RGB, это 256 x 256 x 256, поэтому вам нужно 4096 x 4096 пикселей для их отображения.

Кроме того, нет никакого «естественного» / разумного способа показать их все. По крайней мере, до сих пор никто не придумал двухмерное цветовое пространство, которое действительно имеет смысл. Для отображения цветов вам всегда нужно выбрать 2. Поэтому обычные средства выбора цвета используют либо ползунок оттенка и плоскость яркости / насыщенности , либо плоскость оттенка / насыщенности и ползунок освещенности .

пожалуйста, обратите внимание, что первый (прямоугольный) спектр можно легко нарисовать с помощью двух наложенных градиентов. горизонтальный для оттенка и вертикальный (полупрозрачный) для легкости. это быстрее и полностью плавно (если вы увеличиваете масштаб, вы не видите отдельных линий).

edit: Вот рабочий пример того, как этого можно достичь с помощью одного градиента, что предпочтительно по очевидным причинам:

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

Подход с использованием форм волны немного похож на молоток в поисках гвоздя. просто потому, что битовые операции и тригонометрия являются отличными инструментами, не означает, что вы должны предпочесть их решению, которое намного проще.

...