我遇到了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);
}
}
}
}
答案 0 :(得分:4)
你不能同时拥有所有颜色。所有RGB颜色,256 x 256 x 256,所以你需要4096 x 4096像素才能显示所有颜色。
此外,没有“自然”/明智的方式来展示它们。至少到现在为止,没有人提出真正有意义的二维色彩空间。要显示颜色,您必须总是选择2.这就是常见颜色选择器使用hue slider and a lightness/saturation plane或hue/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);
}
});
}
}
}
使用波形的方法有点像寻找钉子的锤子。仅仅因为位操作和三角函数是很好的工具,并不意味着你应该更喜欢它们更简单的解决方案。