在ActionScript中迭代Bitmap图像的每个像素

时间:2011-03-11 11:10:49

标签: actionscript-3

是否可以迭代位图图像的每个像素?最终我想要实现的是我需要获取位图图像的每个像素的坐标值,并根据它们的坐标值更改这些像素的颜色。在我看来,我需要使用getPixels()方法,但我仍然不明白我应该做什么。

3 个答案:

答案 0 :(得分:3)

您需要一个BitmapData对象。然后,它是一个简单的直接嵌套循环:

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.
   }

}

答案 1 :(得分:3)

(太慢:)) 所以这是sae,如上所述,使用线性循环而不是2个嵌套循环。

//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

请注意,如果您正在使用带有Alpha通道的bitmapData(例如,如果您加载图片,则会自动启用Alpha),您将不得不使用

bd.getPixel32( x, y );// returns a uint : 0xFF000000
//and
bd.setPixel32( x, y, UINT );// 0xFF000000
编辑:我做了一个快速的替补:

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

对于100 *(100 * 100)getPixel,最快(在我的机器上)是带有局部变量的单行for循环。 (+/- 250 ms)然后是单行while(+/- 330 ms):)

存储局部变量w和h的宽度和高度使for循环快两倍:)

很高兴知道

答案 2 :(得分:3)

如果如你所说,你只是根据x和y设置像素,你既不需要getPixel()也不需要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();

但是,如果您想要读取像素的当前值,请加入速度竞赛。

除了早期的答案,这里还有更多的速度增加!

您可以使用getPixels()来获取像素数据的byteArray,而不是多次调用getPixel()。

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