Previous Page
Next Page

Recipe 8.14. Dissolving Between Two Bitmaps

Problem

You want to fade between one bitmap and another.

Solution

Use the pixelDissolve( ) method of the BitmapData class.

Discussion

Like many of the other BitmapData methods, pixelDissolve( ) uses a source and destination bitmap. Each time it is called, it copies a specified number of random pixels from the source bitmap to the destination. To complete a full dissolve, call this method repeatedly, either in an enterFrame handler or a timer-based function. See Recipe 11.1 for information on timer-based animation.

The first time the pixelDissolve( ) method is called, you pass it a random number to use as a seed for the first round of pixel copying. It returns a number that you should keep track of and use as the seed for the next iteration.

Here is the syntax for the method:

seed = srcBmp.pixelDissolve(destBmp, sourceRect, destPoint, 
                            seed, numPixels, fillColor);

  • The sourceRect and destPoint parameters work the same way they do in other BitmapData methods that use two bitmaps. The seed is explained more in Recipe 8.10.

  • The numPixels parameter determines how many pixels are copied each time the method is called.

  • The fillColor offers an easy way of fading a single bitmap to a specified color. If you use the same BitmapData as source and destination, instead of copying identical pixels from one to the other (which would have no visible effect), the chosen pixels are set to the fill color specified in this parameter. You can ignore this when using two different bitmaps.

The first example uses two bitmapsone white, one blackand dissolves between them at 1,000 pixels per frame:

package {
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.geom.Point;

    public class Dissolve extends Sprite {
        private var _bitmap:BitmapData;
        private var _bitmap2:BitmapData;
        private var _image:Bitmap;
        private var _seed:Number;
        private var _pixelCount:int = 0;

        public function Dissolve(  ) {
            _bitmap = new BitmapData(stage.stageWidth,
                                  stage.stageHeight,
                                  false, 0xffffffff);
            _bitmap2 = new BitmapData(stage.stageWidth,
                                   stage.stageHeight,
                                   false, 0xff000000);
            _image = new Bitmap(_bitmap);
            addChild(_image);
            _seed = Math.random(  ) * 100000;
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        public function onEnterFrame(event:Event):void {
            _seed = _bitmap.pixelDissolve(_bitmap2,
                                       _bitmap.rect,
                                       new Point(  ),
                                       _seed,
                                       1000);
            _pixelCount += 1000;
            if(_pixelCount > _bitmap.width * _bitmap.height) {
                removeEventListener(Event.ENTER_FRAME,
                                    onEnterFrame);
            }
        }
    }
}

An important thing to note here is that the pixelDissolve( ) method has no way of knowing when it is done (i.e., when all the pixels have been copied over from one bitmap to the other). It is up to you to keep a count of the number of pixels that have been copied and stop copying when this exceeds the total number of pixels in the image (its width times its height).

In the following example, the same BitmapData is used as both source and destination, and a black fill color is applied:

package {
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.geom.Point;

    public class Dissolve2 extends Sprite {
        private var _bitmap:BitmapData;
        private var _image:Bitmap;
        private var _seed:Number;
        private var _pixelCount:int = 0;
    
        public function Dissolve2(  ) {
            _bitmap = new BitmapData(stage.stageWidth,
                                  stage.stageHeight,
                                  false,
                                  0xffffffff);
            _image = new Bitmap(_bitmap);
            addChild(_image);
            _seed = Math.random(  ) * 100000;
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
    
        public function onEnterFrame(event:Event):void {
            _seed = _bitmap.pixelDissolve(_bitmap,
                                       _bitmap.rect,
                                       new Point(  ),
                                       _seed, 
                                       1000,
                                       0xff000000);
            _pixelCount += 1000;
            if(_pixelCount > _bitmap.width * _bitmap.height)
            {
                removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            }
        }
    }
}

Pixel dissolves are particularly effective when done between two photographic images, at a fast rate. If you don't know what size your images are going to be but you want to keep the speed constant, you can set numPixels to a percentage of the size of the image, like so:

var numPixels:Number = _bitmap.width * _bitmap.height / 100;
_seed = _bitmap.pixelDissolve(_bitmap,
                           _bitmap.rect,
                           new Point(  ),
                           _seed, 
                           numPixels,
                           0xff000000);
_pixelCount += numPixels;

This copies 1/100th of the total pixels on each iteration. At 30 frames per second, this would be (approximately) a 3-second dissolve, regardless of the size of the images.

See Also

Recipes 8.12, 8.13, and 8.15 for other ways to manipulate the content in a bitmap.


Previous Page
Next Page
Converted from CHM to HTML with chm2web Pro 2.85 (unicode)