ActionScript Gradient Banding Problem

Posted by TheDarkIn1978 on Stack Overflow See other posts from Stack Overflow or by TheDarkIn1978
Published on 2010-05-20T10:20:52Z Indexed on 2010/05/20 12:00 UTC
Read the original article Hit count: 214

Filed under:
|

i'm having a strange issue with banding between certain colors of a gradient.

to create the gradient, i'm drawing evenly spaced circle wedges from the center to the border, and filling each circle wedge from a bitmap line gradient pixel in a loop.

public class ColorWheel extends Sprite
{

private static const DEFAULT_RADIUS:Number  = 100;
private static const DEFAULT_BANDING_QUALITY:int = 3600;

public function ColorWheel(nRadius:Number = DEFAULT_RADIUS)
{
    init(nRadius);
}

public function init(nRadius:Number = DEFAULT_RADIUS):void
{
    var nRadians   : Number;
    var nColor     : Number;
    var objMatrix  : Matrix = new Matrix();
    var nX         : Number;
    var nY         : Number;
    var previousX : Number = nRadius;
    var previousY : Number = 0;

    var leftToRightColors:Array = new Array(0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF);
    leftToRightColors.push(leftToRightColors[0]);
    var leftToRightAlphas:Array = new Array();
    var leftToRightRatios:Array = new Array();
    var leftToRightPartition:Number = 255 / (leftToRightColors.length - 1);

    //Push arrays
    for (var j:int = 0; j < leftToRightColors.length; j++)
        {
        leftToRightAlphas.push(1);
        leftToRightRatios.push(j * leftToRightPartition);
        }

    var leftToRightColorsMatrix:Matrix = new Matrix();
    leftToRightColorsMatrix.createGradientBox(DEFAULT_BANDING_QUALITY, 1);

    //Produce a horizontal leftToRightLine sprite
    var leftToRightLine:Sprite = new Sprite();
    leftToRightLine.graphics.lineStyle(1, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
    leftToRightLine.graphics.lineGradientStyle(GradientType.LINEAR, leftToRightColors, leftToRightAlphas, leftToRightRatios, leftToRightColorsMatrix);
    leftToRightLine.graphics.moveTo(0, 0);
    leftToRightLine.graphics.lineTo(DEFAULT_BANDING_QUALITY, 0);

    //Assign bitmapData to the leftToRightLine
    var leftToRightLineBitmapData:BitmapData = new BitmapData(leftToRightLine.width, leftToRightLine.height);
    leftToRightLineBitmapData.draw(leftToRightLine);

    for(var i:int = 1; i < (DEFAULT_BANDING_QUALITY + 1); i++)
    {
        // Convert the degree to radians.
        nRadians = i * (Math.PI / (DEFAULT_BANDING_QUALITY / 2));

        // OR the individual color channels together.
        nColor = leftToRightLineBitmapData.getPixel(i-1, 0);

        // Calculate the coordinate in which the line should be drawn to.
        nX = nRadius * Math.cos(nRadians);
        nY = nRadius * Math.sin(nRadians);

        // Create a matrix for the wedges gradient color.
        objMatrix.createGradientBox(nRadius * 2, nRadius * 2, nRadians, -nRadius, -nRadius);

        graphics.beginGradientFill(GradientType.LINEAR, [nColor, nColor], [1, 1], [127, 255], objMatrix);
        graphics.moveTo( 0, 0 );
        graphics.lineTo( previousX, previousY );
        graphics.lineTo( nX, nY );
        graphics.lineTo( 0, 0 );
        graphics.endFill();
        previousX = nX;
        previousY = nY;
    }
}
}

i'm creating a circle with 3600 wedges, although it doesn't look like it based on the screen shot within the orange color that is produced from gradating from red to yellow numbers. adding a orange number between red and yellow doesn't help. but if i create the circle with only 360 wedges, the gradient banding is much more obvious. 3600 is probably overkill, and doesn't really add more detail over, say, making the circle of 1440 wedges, but i don't know any other way to slightly elevate this banding issue.

any ideas how i can fix this, or what i'm doing wrong? could it be caused by the circleMatrix rotation?

alt text

© Stack Overflow or respective owner

Related posts about actionscript-3

Related posts about gradient