PDA

View Full Version : ShakerAVS. My new filter. Help.


Gatiori
12th July 2007, 22:01
Hi.
I make a new filter. Basicly shake the image by changing amout of radius displacement and frequency of frames.

This is an exemple: http://www.youtube.com/watch?v=WzLJbD20jJQ

This is the code: http://rapidshare.com/files/42560547/shaker.cpp.html

I use BitBlt function, but I have a problem with YV12 colour space, and I wanna make a sub-pixel displacement.

Help me please. :)

How work a sub pixel displacement?

foxyshadis
13th July 2007, 01:19
Use the resizer cores. Something like Spline36Resize(width,height,random1,random2,width,height) (mapped to the C interface), or you could do it entirely in script:


function ShakeItUp(clip c, int "radius") {
radius=default(radius,10)
c
scriptclip(""" Spline36Resize(width,height,random1,random2,width,height) """)
frameevaluate(""" random1 = frand("""+string(radius)+""")
random2 = frand("""+string(radius)+""") """)

function frand(float "mx", bool "signed") {
signed=default(signed,true)
return (Rand(10000)/10000.0)*mx*(signed?sign(rand(2)-.5):1)
}
}
Oops, didn't mean to steal your thunder. >.>

IanB
13th July 2007, 03:22
Of course building a new resizer every frame is going to be slow. You want to build a small farm of resizers, each one doing a particular movement and then select each based on the desired movement for that frame number. Also watch out using random number with frames. One of the rules of the avisynth game is that every time a frame is rerendered it must be identical to every other time it is rendered. A good way to do this is generate and remember framecount random numbers in the constructor and for each GetFrame always use random number N for frame N.


Also whats with this at the global scope. If you have multiple instance of this filter they will interfere with each other. int x,y;
float x2,y2,xe,ye,xj,yj,xs,ys,xx,yy;

tin3tin
13th July 2007, 10:21
@ Gatiori
Very nice and human/handheld-looking shakes. :)

A fun idear!

Gatiori
8th August 2007, 22:00
Ok Tanks!!!

I wrote again:

x=xfloat[index-1];
y=yfloat[index-1];

AVSValue args[7] = { child, vi.width,vi.height,-(xfloat[index]),yfloat[index],vi.width+0.01,vi.height+.01 };
resized = env->Invoke("Spline16Resize",AVSValue(args,7)).AsClip();
src1 = resized->GetFrame(n, env);
env->BitBlt(dstp,dst_pitch,src1p,src1_pitch,kb * (bwd),src1_height);

if (x!=0) {
args[3]=xfloat[index]-int(xfloat[index]); args[4]=yfloat[index]-int(yfloat[index]);
resized2 = env->Invoke("Spline16Resize",AVSValue(args,7)).AsClip();
src2 = resized2->GetFrame(n, env);
for (w=0; w<abs(x); w++) {
env->BitBlt(dstp+(((x>0)?x-w:bwd+x+w)*kb)+(((y>0)?y:0)*dst_pitch),dst_pitch,src2p+(((x>0)?w:bwd-w-1)*kb)+((y>0)?0:-y*src2_pitch),src2_pitch,kb ,src2_height-abs(y));
}
}
if (y!=0) {
args[3]=-(xfloat[index]-int(xfloat[index])); args[4]=-(yfloat[index]-int(yfloat[index]));
resized3 = env->Invoke("Spline16Resize",AVSValue(args,7)).AsClip();
src3 = resized3->GetFrame(n, env);
for (h=0; h<abs(y); h++) {
env->BitBlt(dstp+(((x>0)?x:0)*kb)+( ((y>0)?(y-h):(dst_height+y+h)) *dst_pitch),dst_pitch,src3p+((x>0)?0:-x*kb)+(((y>0)?h:src3_height-h-1) * src3_pitch),src3_pitch,kb*(bwd-abs(x)) ,1);
}
}

return dst;

The process are completely solved by subpixel.
... but this code is very slow.

How to make more fast?

IanB
9th August 2007, 00:07
You want to build a small farm of resizers, each one doing a particular movement and then select each based on the desired movement for that frame number.As I said prebuild all the resizers in the constructor. Save them in a class scope array. Use these in the GetFrame instead of env->Invoke'ing a new one every frame.

Remember the resizer core does horizontal and vertical resizing as 2 distinct steps, you do likewise to minimise the number of resizers instances needed. Generate X only movement separately from Y only movement resizers and then chain them in the GetFrame. By quantizing your movement vectors cleverly you would be able to do 256 distinct movements with only 16 X only resizers and 16 Y only resizers.

You will need an intermediate dummy class to act as a selector so you can have a constant 'child' member for every resizer.

:Edit: In fact completly separate your filter into a horizontal only shaker and a vertical only shaker. In the create call do "return new HShake(new VShake(child,...), ...)"