… wider range for displacementMapFilter
February 18, 2008
TubeView -filter
version in actionScript 3.0, using two DisplacementMapFilters
But why two displacementMaps ? ‘cos one can only shift a pixel
within a range of -127*scale to 127*scale pixels ! So that if the displacement needed is like for instance 205 pixels, why don’t handle 200 with one and the remaining 5 with another filter ?
The idea breafly with some extracts from the code:
// creating two displacementMaps,// we have the needed displacement (dx, dy), // from that amount the lower bytes create 'dismapLo', the higher dismapHi var green:int = dx*0x10 +0x8080; // multiplied by 16: var blue:int = dy*0x10 +0x8080; // smallest shift 1/16 pixel for better quality dismapHi.setPixel(x,y, (green & 0xFF00) | (blue>>); dismapLo.setPixel(x,y, (green & 0xFF) <<8 | (blue & 0xFF) ); ... // nb: the scaling of bitmaps ! var displaceHi:DisplacementMapFilter= new DisplacementMapFilter(dismapHi, new Point(x-bmp.width,y-bmp.height), BitmapDataChannel.GREEN, BitmapDataChannel.BLUE, 0x1000,0x1000, // larger shift ! DisplacementMapFilterMode.COLOR, 0x0,0.0); // use mode ´COLOR´ gives the effect on the edges of the bitmap var displaceLo:DisplacementMapFilter= new DisplacementMapFilter(dismapLo, new Point(x-bmp.width,y-bmp.height), BitmapDataChannel.GREEN, BitmapDataChannel.BLUE, 0x10,0x10, // smaller shift ! DisplacementMapFilterMode.COLOR, 0x0,0.0); bmp.applyFilter(bmpOriginal,new Rectangle(0,0,bmp.width,bmp.height), new Point(0,0) ,displaceHi); bmp.applyFilter(bmp,new Rectangle(0,0,bmp.width,bmp.height), new Point(0,0) ,displaceLo); ...
… my first actionscript-blog posting, stay tuned for more to come

May 31, 2008 at 7:30 pm
So interesting…. Thanks for this sample.
I’m trying to achieve a simple horizontal flip with the displacementmap filter but with no success. Basically I’m using a white-to-black gradient but I can’t get the flipped image. Can you give me any hint?
Lots of thanks in advanced.
Alberto
June 1, 2008 at 7:44 pm
Ok, thanks for your comment.
Hint 1:
… as an example some code for reflecting upper half of the stage, MainTimeline, frame1:
// actionscript 3.0, code example
// anything for drawing something on the stage
addChild(something);
// dimensions of the stage
var w:int = stage.stageWidth;
var h2:int = stage.stageHeight/2; // half the stage height
// matrix for a vertical gradient
var gratrix:Matrix = new Matrix();
gratrix.createGradientBox(w, h2, // width,half the height,
Math.PI/2, // rad for 90 degrees
0, 0); // translate, in this case start from origin point
// temporary sprite for drawing the fill
var gradSprite:Sprite = new Sprite();
gradSprite.graphics.beginGradientFill(GradientType.LINEAR,
[0x807F, 0x8000], // green constantly 0×80 - no replacement, blue transfers from 127 - the above pixel - to zero,
[1, 1], // alphas, not significant
[0x00, 0xFF], // ratios, linear fill
gratrix );
gradSprite.graphics.drawRect(0,0,w, h2); // fill, half the stage size
gradSprite.graphics.endFill();
var displaceBmp:BitmapData = new BitmapData(w,h2,false); // half the stage, no alpha channel
displaceBmp.draw(gradSprite); // copy gradient fill to bitmapdata
var displacer:DisplacementMapFilter = new DisplacementMapFilter(
displaceBmp,
new Point(0,h2), // locates this filter below the horizontal middleline
BitmapDataChannel.GREEN, // displacement in x-direction
BitmapDataChannel.BLUE, // displacement in y-direction
0.0,4*h2); // scales, in this case only the blue component matters
this.filters = [displacer];
Hint 2:
I guess with PixelBender lots like this will be a whole lot easier: Adjusting displacementFilter for precise result can be a bit annoying, this tube view came out surprisingly well, but when I tried like a fish-lens or spherical effect, it did look good at all.
June 2, 2008 at 7:26 am
Lots of thanks pixelero! I will try it later.
I agree; with PixelBender this will a lot easier, but the problem is that I can’t use it in my project (I must use a BitmapFilter and, as you said , is very annoying - to say the least - to configure a displacementFilter to work “exactly”).
Will post the results.
Lots of thanks!!
Alberto
June 2, 2008 at 6:47 pm
Hi again,
I’ve tested the code and the result is the same as I could get; the image appears flipped but I think that only works for images smaller than 255. For bigger ones I see “bands” that aren’t flipped.
I’ve upload a sample:
http://www.theklue.com/test.png
I suppose that the problem is that we can’t detect more than 255 levels of the same color…
Have any clue?
Thanks again!
June 2, 2008 at 7:02 pm
In this example you use two displacementMaps for the same reason, isn’t it? But I’m using a class that (for project requirements) has to return a single BitmapFilter, so I can’t do an approach like yours…
Oh, i’m getting desperate right now…
June 3, 2008 at 7:06 pm
Yes, having only 128 or 256 levels does cause the bands.
Btw, why does it have to be DisplacementMapFilter ?
If it’s only mirroring the stage, aren’t there some other ways of doing that, maybe BitmapData.draw(stage)?
var w:int = stage.stageWidth;
var h2:int = stage.stageHeight/2;
var reflectMap:BitmapData = new BitmapData(w,h2, true, 0×00); // half size again
// reflectMap.draw(stage); // or addEventListener…
var reflectBmp:Bitmap = new Bitmap(reflectMap);
reflectBmp.y = stage.stageHeight;
reflectBmp.scaleY = -1.0;
addChild(reflectBmp);
addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(e:Event):void {
reflectMap.fillRect(reflectMap.rect, 0×00); // this line is necesserly if animated with transparent parts
reflectMap.draw(stage);
}
June 3, 2008 at 10:00 pm
Yes, this way is a lot easier, but I have an image editor and -for project limitations- I need to use BitmapFilters.
I was thinking into extending the DisplacementMap filter or to create a whole new one but sincerely I don’t know how to begin.
Anyway thanks for your time and effort