Recently I wrote about my distortion effect. Believe me, I experimented with it a lot. And it was damn slow on big bitmaps. But here’s a funny way to do it through native jpeg decoding. And it runs smooth on relatively big bitmaps. The guy messes up with jpeg data in ByteArray many times in a row loading it over and over again. Letting Flash native jpeg decoder do the work for him. This is is a great example of creative thinking!
Tag Archive for 'Distortion'
You should have seen the effect of a TV signal glitch on text at my last va.lent.in site. People keep asking me how it was done over and over again. I won’t post complete source code here because it’s kind of messy. I’ll just give basic ideas, because this effect is rather simple.
Basically, you just displace red, green and blue channels of a bitmap separately and apply the same actions to resulting bitmap. Adding some kind of wave function looks cool too, but is damn slow. So, what I decided to do is to distort a small rectangle of target image over a couple of frames. First, I used only BitmapDatas but later tried to test PixelBender performance. Honestly, I don’t remember any miraculous speed gain, so there might be none at all. But anyway, here’s the code of this filter. Basically, it’s just 3 lines of code:
void evaluatePixel()
{
float2 outCoords = outCoord();
dst.r = sample( src, float2(outCoords.x + rOffset, outCoords.y) ).r;
dst.g = sample( src, float2(outCoords.x + gOffset, outCoords.y) ).g;
dst.b = sample( src, float2(outCoords.x + bOffset, outCoords.y) ).b;
}
Full source code you can download here: RGBDisplacement.pbk
This shader takes 3 displacement values as parameters. Now back to AS3. Once again, this code is result of numerous experiments, changes and fixes during development. Please don’t use it as is (actually it doesn’t work alone) but rather try to understand the basic idea.
[Embed(source="filters/RGBDisplacement.pbj", mimeType="application/octet-stream")]
private var ShaderDistort:Class;
public function Distortion( source: Sprite, minAmp: int = 10, maxAmp: int = 40, len: int = 30, minRand: Number = .05, ampRand: Number = .8, maxH: int = 20 )
{ ... }
Shader class and constructor params.
public function start( interval: int = -1 ): void
{
if ( bitmapData.width != Math.ceil(_source.width) || bitmapData.height != Math.ceil(_source.height) )
{
initBitmaps();
}
seed = 0;
_source.alpha = 0;
visible = true;
this.interval = interval;
// set random displacement
bmpY = Math.random()*(bitmapData.height-bitmapDataDistorted.height);
bitmapData.fillRect( bitmapData.rect, 0x000000 );
bitmapData.draw( _source );
business();
}
This method resets distortion params, sets bmpY to a random starting y position and invokes business() which does the job.
private function business( evt: Event = null ): void
{
// stop if played for certain number of frames
if (interval == 0)
{
stop();
return;
}
interval--;
// randomly move the effect up or down
bmpY += int((10 - Math.random()*20) * Math.sqrt(interval));
bmpY < 0 ? bmpY = 0 : true;
bmpY > bitmapData.height-bitmapDataDistorted.height ? bmpY = bitmapData.height-bitmapDataDistorted.height : true;
var bmpd: BitmapData = new BitmapData( bitmapDataDistorted.width, bitmapDataDistorted.height, false, 0x000000 );
bmpd.copyPixels( bitmapData, new Rectangle(0, bmpY, bitmapDataDistorted.width, bitmapDataDistorted.height ), new Point(0, 0) );
filter.data.src.input = bmpd;
seed++;
seed >= len ? seed = 0: true;
// wave function
var v: Number = 3.14159265 / len * seed;
// approximation of sin()
var sin: Number = 1.27323954 * v - 0.405284735 * v * v;
var amp: Number = minAmp + sin * difAmp;
var i: int = 0;
var disp: Array = [];
var pi2: Number = 6.28318531;
for (i; i<3; i++)
{
if ( seeds[i] >= 1 )
{
seeds[i]--;
dSeeds[i] = Math.random() * ampRand + minRand;
}
seeds[i] += dSeeds[i];
v = seeds[i] * pi2;
// approximation of sin()
if (v > 3.14159265) v -= 6.28318531;
if (v < 0)
sin = 1.27323954 * v + .405284735 * v * v;
else
sin = 1.27323954 * v - 0.405284735 * v * v;
disp[i] = sin * amp;
}
// set displacements for shader
filter.data.rOffset.value = [disp[0]];
filter.data.gOffset.value = [disp[1]];
filter.data.bOffset.value = [disp[2]];
// invoke shader
var job: ShaderJob = new ShaderJob(filter, bitmapDataDistorted);
job.addEventListener(ShaderEvent.COMPLETE, redraw);
job.start();
}
And finally redraw() method
private function redraw( evt: Event = null ): void
{
bitmapData.copyPixels( bitmapDataDistorted, bitmapDataDistorted.rect, new Point(0, bmpY) );
id = setTimeout(business, 40);
}
That’s it. You can refer to my post about using Maple for more math.
The source of this class is here: Distortion.as













Recent Comments