开发者

Iterating each pixel of a Bitmap image in ActionScript

Is it possible to iterate each pixel of a 开发者_JAVA百科bitmap image? Eventually what I'm trying to achieve is that I need to get the coordinate values of each pixel of a bitmap image and change the color of those pixels according to their coordinate values. As I see it, I need to use the getPixels() method but I still did not understand exactly what I should do.


( too slow :) ) so this is the sae as above with a linear loop instead of 2 nested loops.

//creates a new BitmapData, with transparency, white 0xFFFFFF
var bd:BitmapData = new BitmapData( 100, 100, false, 0xFFFFFF );

//stores the width and height of the image
var w:int = bd.width;
var h:int = bd.height;

var i:int = w * h;

var x:int, y:int, col;
//decremental loop are said to be faster :)
while ( i-- )
{
    //this is the position of each pixel in x & y
    x = i % w;
    y = int( i / w );

    //gets the current color of the pixel ( 0xFFFFFF )
    col = bd.getPixel( x, y );

    //assign the 0xFF0000 ( red ) color to the pixel
    bd.setPixel( x, y, 0xFF0000 );

}
addChild( new Bitmap( bd ) );//a nice red block

note that if you're using a bitmapData with an alpha channel (say if you load the image, the alpha will be turned on automatically ) you 'll have to use

bd.getPixel32( x, y );// returns a uint : 0xFF000000
//and
bd.setPixel32( x, y, UINT );// 0xFF000000

EDIT : I 've done a quick bench :

package  
{
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.utils.getTimer;
public class pixels extends Sprite 
{
    private var bd:BitmapData = new BitmapData( 100, 100, false, 0xFFFFFF );
    public function pixels() 
    {
        var i:int, total:int = 100, t:int = 0;

        t = getTimer();
        i = total;
        while( i-- )
        {
            whileLoop( bd );
        }
        trace( 'while:', getTimer() - t );

        t = getTimer();
        i = total;
        while( i-- )
        {
            forLoop( bd );
        }
        trace( 'for:', getTimer() - t );
    }

    private function forLoop( bd:BitmapData ):void 
    {
        var i:int, j:int;
        var col:int;

        for ( i = 0; i < bd.width; i++ ) 
        {
            for ( j = 0; j < bd.height; j++ )
            {
                col = bd.getPixel( i, j ); // +/- 790 ms
            }
        }

        //for ( i = 0; i < bd.width; i++ ) for ( j = 0; j < bd.height; j++ ) col = bd.getPixel( i, j ); // +/-530 ms

        //var w:int = bd.width;
        //var h:int = bd.height;
        //for ( i = 0; i < w; i++ ) for ( j = 0; j < h; j++ ) col = bd.getPixel( i, j ); // +/-250 ms

    }

    private function whileLoop( bd:BitmapData ):void 
    {
        var w:int = bd.width;
        var h:int = bd.height;
        var i:int = w * h;
        var col:int;
        while ( i-- ) 
        {
            col = bd.getPixel( i % w, int( i / w ) ); //  +/- 580 ms
        }
        //while ( i-- ) col = bd.getPixel( i % w, int( i / w ) ); //  +/- 330 ms
    }
}
}

for 100 * ( 100 * 100 ) getPixel, the fastest (on my machine) is the one-line for loop with local variables. ( +/- 250 ms ) then the one-line while( +/- 330 ms ) :)

storing local variables w and h for width and height makes the for loops twice faster :)

good to know


If, as you say, you are only setting the pixels based on their x and y, you need neither getPixel() nor getPixels()!

myBitmapData.lock();

for( var j:int = 0; j < myBitmapData.height; j++ )
{
    for( var i:int = 0; i < myBitmapData.width; i++ )
    {
        var alpha:uint = 0xFF000000;  // Alpha is always 100%
        var red:uint = 0x00FF0000 * ( i / myBitmapData.width );  // Set red based on x
        var green:uint = 0x0000FF00 * ( j / myBitmapData.height );  // Set green based on y
        var newColor:uint = alpha + red + green;  // Add the components

        // Set the new pixel value (setPixel32() includes alpha, e.g. 0xFFFF0000 => alpha=FF, red=FF, green=00, blue=00)
        myBitmapData.setPixel32( i, j, newColor );
    }
}

myBitmapData.unlock();

If, however, you want to read the pixels' current value, let me join the speed competition.

In addition to earlier answers, here's much more speed increase!

Instead of numerous calls to getPixel(), you can use getPixels() to get a byteArray of the pixel data.

myBitmapData.lock();

var numPixels:int = myBitmapData.width * myBitmapData.height;
var pixels:ByteArray = myBitmapData.getPixels( new Rectangle( 0, 0, myBitmapData.width, myBitmapData.height ) );
for( var i:int = 0; i < numPixels; i++ )
{
    // Read the color data
    var color:uint = pixels.readUnsignedInt();

    // Change it if you like

    // Write it to the pixel (setPixel32() includes alpha, e.g. 0xFFFF0000 => alpha=FF, red=FF, green=00, blue=00)
    var theX:int = i % myBitmapData.width;
    myBitmapData.setPixel32( theX, ( i - theX ) / myBitmapData.width, color );
}

myBitmapData.unlock();


You need a BitmapData object. Then, it's a simple straight-forward nested loop :

var pix : int; //AS3 uses int even for uint types

for (var x:int = 0; x < myBitmapData.width; x++)
{
   for (var y:int = 0; y < myBitmapData.height; y++)
   {
      // This'll get you the pixel color as RGB
      pix = myBitmapData.getPixel(x,y);
      // To change the color, use the setPixel method + the uint corresponding
      // to the new color.
   }

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜