How to slice up a movie using ActionScript

 

In this guide I'm going to explain how to slice up a running movie clip in Flash using ActionScript 3.0. Click here to see an example of this used in a game.

To be able to work on a movie we first need to understand what a movie is. A movie is a sequence of images giving the illusion of continuous movement. Each image in the movie is referred to as a frame. We can start by discussing how to slice up one image because each frame of the movie is an image. Then it will be easy to expand that knowledge into slicing a movie made up of many images.

To do this we are going to catch a frame of the movie as an image. An image in ActionScript is represented by the class Bitmap. The Bitmap object holds a reference to an object of type BitmapData. The BitmapData holds the pixel information that makes up the image. We start by creating a Bitmap object and a BitmapData object. We set the width and height of the BitmapData. After that we set the bitmapData property of the Bitmap object to the created BitmapData object.

var tBitmap:Bitmap = new Bitmap();
var tBD:BitmapData = new BitmapData(width, height);
tBitmap.bitmapData = tBD;

We use the draw method of the BitmapData class to capture a slice of the frame of the movie as an image.

public function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void

The first parameter to this method is source. This is the object that will be drawn as an image in the BitmapData object. We are also going to use the parameters matrix and clipRect. Together these to parameters defines which part of the frame we want to capture and draw in the BitmapData object. The parameter matrix defines how to scale, rotate and shift the pixels that are captured from the movie. We are only interested in the shifting part in this example. We need the shifting part of the matrix to be able to define which part of the movie to capture as the image. We use the parameter clipRect to define the size of the slice, clipRect is an object of the class Rectangle and defines the width and height of the slice to capture using the draw method.

var tBitmap:Bitmap = new Bitmap();
var tBD:BitmapData = new BitmapData(width, height);
var tM:Matrix = new Matrix();
tM.translate(x, y);
var tR:Rectangle = new Rectangle(0, 0, width, heigh);
tBD.draw(source, tM, null, null, tR);
tBitmap.bitmapData = tBD;

The code above will capture the part of source that is bound by a rectangle with the width and height defined by the rectangle and that is located at the coordinate x, y specified by the matrix. See the image bellow.

Bild som visar placering och storlek på utklippet

We have only cut out one part of the frame so far. We need to repeat the code above to slice the hole frame up into different images. In the example bellow we slice the frame into nine parts. Three horizontal and three vertical images.

Bild som visar hur filmrutan delas upp i nio lika stora delar

protected function slice(rSource:DisplayObject):void
{
   var tTilesOneDirection:uint = 3;
   var tWidth:Number = rSource.width / tTilesOneDirection;
   var tHeight:Number = rSource.height / tTilesOneDirection;
   var tBitmap:Bitmap;
   var tBD:BitmapData = new BitmapData(tWidth, tHeight, false); 
   var tM:Matrix = new Matrix();
   var tR:Rectangle = new Rectangle(0, 0, tWidth, tHeight);
   var i:uint;
   var j:uint;
   for (i = 0; i < pTilesOneDirection; i++)
   {
      for (j = 0; j < pTilesOneDirection; j++)
      { 
         tM = new Matrix();
         tM.translate(-i * tWidth, -j * tHeight);
         tBD.draw(rSource, tM, null, null, tR);
         tBitmap = new Bitmap();
         tBitmap.bitmapData = tBD.clone();
         addChild(tBitmap);
      }
   }
   tBD.dispose();
}

We start by defining how many parts we want to slice the frame into. Then we can calculate the width and height of each slice by dividing the width and height of the frame by the number of slices in each direction.

Now we create a new Bitmap, BitmapData, Matrix and Rectangle as before. But we don't set the translation in the matrix just yet because it will be different for each slice of the frame. The translation will be set inside the loops that create each slice. We create two different loops, one for the horizontal cuts and one for the vertical ones. The parameters i and j defines which part of the frame to capture as the current slice. We multiply j with the width of the slice and i with the height to calculate the coordinates of the translation.

Then we call the draw method as before. We also need to create a new Bitmap object for each slice that we cut the frame into to be able to show all the slices at the same time. We pass a copy of the captured BitmapData object to the new Bitmap object. We do this because the Bitmap object takes a reference to the BitmapData object and we use the same BitmapData object for all the cuts. If we don't pass a copy then all the Bitmap object will have a reference to the same BitmapData object and therefor show the same image.

Finally we call the dispose method on the BitmapData to free the memory that is used to store the BitmapData object. To see anything on the screen we also need to add the Bitmap objects to the display list using the addChild method.

This is all it takes to slice a frame into smaller images. Now that we know how to slice one frame of the movie we can repeat the same procedure for each frame of the movie, slicing the hole movie. One way to do this is to listen for the onEnterFrame event and repeat the code above for each frame. If we do this then it can be a good idea to store the Bitmap objects outside of the slice method and reuse the objects for each frame. Then we only need to change the BitmapData information of the Bitmap objects and don't need to recreate the Bitmap objects for each frame.

That is all for this tutorial about slicing bitmaps in Flash Builder 4.5 using the Flex framework.