03 May 2010

AS3: Dynamic Bitmap Split Function

Recently I had most rewarding moments while playing around with Bitmap and BitmapData classes in ActionScript3.0 and also I must mention how this becomes more fun than really learning the language.

While reading about copying pixels from one Bitmap to another this idea fall into my mind about writing function to allow me to split any loaded or drawn image into desired number of columns and rows. Solution was quite easy actually, with a little help of ByteArray class.

Here is the function which allows you to do just that, dynamic split of any image:


function splitBitmap(_source:BitmapData, _columns:int, _rows:int):void
{
var _bitmapWidth:int = _source.width;
var _bitmapHeight:int = _source.height;

var _onePieceWidth:Number = Math.round(_bitmapWidth / _columns);
var _onePieceHeight:Number = Math.round(_bitmapWidth / _rows);

var _copyRect:Rectangle = new Rectangle(0, 0, _onePieceWidth, _onePieceHeight);
for(var i:int = 0; i < _columns; i++)
{
var tempArray:Array = new Array();

for(var j:int = 0; j < _rows; j++)
{
var _piece:String = "piece"+String(i)+String(j);
var temp:* = [_piece];
temp = new BitmapData(_onePieceWidth, _onePieceHeight, true, 0xFF0000CC);

var newBytes:ByteArray = _source.getPixels(_copyRect);
newBytes.position = 0;
temp.setPixels(_copyRect, newBytes);

var _newBitmap:String = "newBitmap"+String(i)+String(j);
var tempBitmap:* = [_newBitmap];
tempBitmap = new Bitmap(temp);

tempBitmap.x = i * (_onePieceWidth) + bm1.x;
tempBitmap.y = j * (_onePieceHeight)+ bm1.y;
addChild(tempBitmap);

tempArray.push(tempBitmap);
}
bitmapsArray.push(tempArray);
}
}


Setting tempBitmap x and y properties is optional, because I wanted to put new pieces in original place (above bm1, original Bitmap) so viewer can't see these are new

DisplayObjects. In this way transition effect is masked. You may also notice bitmapsArray, two-dimensional Array to hold all pieces in one place for later easy manipulation.

There can be some improvements to it, like limiting max number of columns and rows or adding image import with Loader class etc. but main functionality is there, working like a charm. Now, you can use this function to produce all kinds of transition effects and image manipulations. Some examples might follow in future posts.

*_*

4 comments:

Philippe said...

Pretty inefficient IMHO.

For transition or effects you should by doing a bitmapFill into shape slices.

flanture said...

Phillippe, any example links you would like to share? Thanx.

___peps said...

Hey nice function!

I happened to work on a project and I needed to slice my pictures too. I came up with a version which is a little more optimized with vectors instead of arrays, and avoiding loop inside another loop with a while statement here it is :

public function Face(_bmp:Bitmap, _column:int, _rows:int)
{
var img:Bitmap = _bmp;
var COLUMNS:int = _column;
var ROWS:int = _rows;

const PIECES_NB:int = COLUMNS * ROWS;
const PIECES_WIDTH:int = img.width / COLUMNS;
const PIECES_HEIGHT:int = img.height / ROWS;



_pieces = new Vector.(PIECES_NB, true);
_img_coordinates = new Vector.>(PIECES_NB, true);

const p:Point = new Point(0,0);

var i:int = 0;

var __x:int;
var __y:int;
var __z:int;


while( i < PIECES_NB )
{
// create a new piece of the image
bmp = new Bitmap(new BitmapData(PIECES_WIDTH, PIECES_HEIGHT));
bmp.bitmapData.copyPixels(img.bitmapData,
new Rectangle( (i % COLUMNS ) * PIECES_WIDTH,
int(i / COLUMNS) * PIECES_HEIGHT,
PIECES_WIDTH,
PIECES_HEIGHT),
p);

// create new sprite and add bitmap data to it
newPiece = new Sprite();
newPiece.addChild(bmp);

// store the Sprite to the img_piece vector
_pieces[i] = newPiece;

// store the coordinates of the bitmap inside a new Vector
__x = (i % COLUMNS ) * PIECES_WIDTH - X_OFFSET;
__y = Y_OFFSET - int(i / COLUMNS) * PIECES_HEIGHT;
__z = 0;

_coordinates = new Vector.(4, true);
_coordinates[0] = __x;
_coordinates[1] = __y;
_coordinates[2] = __z;


// add those coordinates to the vector that stores
// all the positions for all the piece that compose the image
_img_coordinates[int(i)] = _coordinates;


i++

}
}

I had to have 3D coordinates so I stored all the coordinates of the images inside a two 2D vector.

You can see an exemple of the sliced pictures mapped on 3D cubes here : http://www.electronslibres.ca/?p=280

Cheers !

Darshan Gopinath said...

i think you meant : var _onePieceHeight:Number = Math.round(_bitmapHeight / _rows);

thx for the code :)

 

template by blogger templates