Friday, February 8, 2019

Four ways for per pixel bitmap manipulation in OpenFL

A BitmapData can be seen as an array of length width*height, holding unsigned int colors values. There are at least four ways to manipulate pixels of a bitmap image(Bitmap/BitmapData) in OpenFL. The first way is using setPixel() or setPixel32() function:

var myBitmapData:BitmapData = new BitmapData(800, 600, true, 0);
myBitmapData.lock();
for (j in 0...600)
    {
    for (i in 0...200)
        {
         myBitmapData.setPixel32(i, j, (i % 255) << 24 | 0x0000ff);
        }
    }
myBitmapData.unlock();
You can use lock() and unlock() function before and after multiple calls of setPixel() function, so the BitmapData will only be updated on Screen after unlock(). The second way is using setVector() function, and a Vector of UInt to hold pixel values:
var myVector:Vector = new Vector(200 * 600, true);
for (j in 0...600)
    {
    for (i in 0...200)
        {
        myVector[j * 200 + i] = (i % 255) << 24 | 0x0000ff;
        }
    }
var myRect2:Rectangle = new Rectangle(200, 0, 200, 600);
myBitmapData.setVector(myRect2,myVector);
The third way is using setPixels() function, and a ByteArray to hold pixel values:
var myByteArray:ByteArray = new ByteArray(200 * 600 * 4);
for (j in 0...600)
   {
   for (i in 0...200)
       {
       //myByteArray.position = (j * 200 + i) * 4;
       myByteArray.writeUnsignedInt((i % 255) << 24 | 0x0000ff);
       }
   }
var myRect4:Rectangle = new Rectangle(400, 0, 200, 600);
myByteArray.position = 0;
myBitmapData.setPixels(myRect4,myByteArray);
Remember to set the position of the ByteArray to 0 before calling setPixels(). The position "(j * width + i) * 4" of the ByteArray is associated with the pixel at (x=i,y=j) in the BitmapData. There is no need to set the position of the ByteArray to "(j * 200 + i) * 4" above since in the double for loops the "writeUnsignedInt()" function will update the position automatically. The fourth way is using the Memoery API, which is similar to the third way. See https://bruce-lab.blogspot.com/2013/03/fast-way-for-per-pixel-bitmap.html for more details.
var myMem:ByteArray = new ByteArray(200 * 600 * 4);
Memory.select(myMem);
for (j in 0...600)
    {
    for (i in 0...200)
        {
        Memory.setI32((j * 200 + i) * 4, (i % 255) << 24 | 0x0000ff);
        }
    }
var myRect4:Rectangle = new Rectangle(600, 0, 200, 600);
myMem.position = 0;
myBitmapData.setPixels(myRect4,myMem);
The full source code: See the result here (HTML5): http://vvv.flaswf.tk/demo/?url=BitmapDataPixel

Sponsors