Bringing life to an image

| 2 min read

Here is how to bring life to an image using the filter DisplacementMapFilter.

Click here to see the demo.

I got the idea from a video made by Chad Perkins (thanks Chad, you're giving me a lot of inspiration!) where he is showing this effect in After Effects. My Flash nature pushed me to reproduced it with AS3. The result is great even if the After Effects version is slightly better, maybe the Flash version can be tweaked a bit more.

Here is how it works. I used this wonderful picture from my friend Ziemowit Maj :)

You also need a second picture that will describe the map of the filter using luminance. The foreground areas should be whiter than the background areas. I made this picture using Photoshop, the brush tools, and of course my proven drawing skills :D

I apply the DisplacementMapFilter on a BitmapData and I move the map position over time. It is not too complicated, but you can probably spend more time than me to draw the map correctly. Be careful not to make a distortion too big or it will look weird! Here is the code:

package {
import caurina.transitions.Tweener;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.PixelSnapping;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.Point;
import flash.geom.Rectangle;

/**
* <b>Author:</b> Romuald Quantin - <a href="http://www.soundstep.com/" target="_blank">www.soundstep.com</a><br />
* <b>Company:</b> Less Rain - <a href="http://www.lessrain.com/" target="_blank">www.lessrain.com</a><br />
* <b>Class version:</b> 1.0<br />
* <b>Actionscript version:</b> 3.0<br />
* <b>Copyright:</b>
* <br />
* <b>Date:</b> Aug 16, 2010<br />
* <b>Usage:</b>
* @example
* <listing version="3.0"></listing>
*/


public class Main extends Sprite {

[Embed(source="../assets/photo.jpg")]
private var Photo:Class;
[Embed(source="../assets/map.jpg")]
private var Map:Class;

private var _photo:Bitmap;
private var _map:Bitmap;
private var _point:Point;
private var _photoDisplaced:Bitmap;
private var _photoDisplacedData:BitmapData;
private var _filter:DisplacementMapFilter;

private var _range:Number = 17;

//------------------------------------
// private, protected properties
//------------------------------------



//------------------------------------
// public properties
//------------------------------------



//------------------------------------
// constructor
//------------------------------------

public function Main() {
initialize();
}

//
// PRIVATE, PROTECTED
//________________________________________________________________________________________________

private function initialize():void {
// stage
stage.frameRate = 41;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// photo
_photo = new Photo();
// photoDisplaced
_photoDisplacedData = new BitmapData(_photo.width, _photo.height);
_photoDisplaced = new Bitmap(_photoDisplacedData, PixelSnapping.AUTO, true);
_photoDisplaced.scaleX = 1.05;
_photoDisplaced.scaleY = 1.05;
_photoDisplaced.x = (stage.stageWidth - _photo.width) >> 1;
_photoDisplaced.y = (stage.stageHeight - _photo.height) >> 1;
addChild(_photoDisplaced);
// map
_map = new Map();
// point
_point = new Point(-(_range), 0);
// enterframe
addEventListener(Event.ENTER_FRAME, loop);
// scroll motion
move(_range);
}

private function move(target:Number):void {
Tweener.addTween(_point, {time:2, x:target, transition:"linear", onComplete:move, onCompleteParams:[target*-1]});
}

private function loop(event:Event):void {
_filter = new DisplacementMapFilter(
_map.bitmapData,
_point,
BitmapDataChannel.RED,
BitmapDataChannel.RED,
_point.x,
_point.y,
DisplacementMapFilterMode.WRAP);
_photoDisplacedData.applyFilter(_photo.bitmapData, _photoDisplacedData.rect, new Point(0,0), _filter);
_photoDisplaced.bitmapData.draw(_photoDisplacedData, null, null, null, new Rectangle( _point.x, _point.y, _photo.width, _photo.height), true);
}

// PUBLIC
//________________________________________________________________________________________________



}
}