View Full Version : Total noob requesting some coding help - Displacement plugin
Mcmount
19th April 2012, 17:52
Hi,
I'm writing (improving) my displacement plugin and could really use some help. Basic idea is that plugin gets 2 input images; rgb foreground and greyscale map, which shifts rgb foreground pixels according the luminance value of the greyscale image.
For sake of simplicity and total lack of coding skills I'm using only RGB32.
My plugin works quite nice exept - changes in greyscale image creates 4 pixel hops to rgb image. Like really bad aliasing.
This is the short main code;
for (int y = 0; y < frame_height; y++) { // Loop from bottom line to top line.
for (int x = (frame_row_size - 4); x >=0 ; x-=4) { // 1 pixel = 4 bytes (fourth byte = red)
int z = windowp[x+4]/dev*4;
if ((x+z)<frame_row_size-4)
{
framep[x+z] = framep[x];
framep[x+z+1] = framep[x+1];
framep[x+z+2] = framep[x+2];
framep[x] = framep[x-z];
framep[x+1] =framep[x-z+1];
framep[x+2] =framep[x-z+2];
}
else
{
framep[x]=framep[x];
}
dev is just devider, which defines how strong the shift is. Windowp is the greyscale image. How in earth I can get the pixel shiftment smoother?
I would really appriciate some help!
Br, Mcm
wonkey_monkey
19th April 2012, 20:27
I'm not quite following your code, but first I'm wondering why you have:
int z = windowp[x+4]/dev*4;
^^ ?
That looks like you're looking one pixel to the right (which will be off the end of the line at the start of the x loop) of where you intend to.
Then I wonder why you're writing two pixels at each iteration. This seems wasteful - asuming I understand what you're trying to achieve, I'd do it like this (assuming single-channel images for simplicity):
for (x=w-1; x>=0; x--) {
z=x+windows[x];
if (x-z>=0) framep[x]=framep[x+windowp[x-z]];
}
Your way, it seems like the pixel at [x+z] is getting the shift at windowp[x], when you've already written it with the shift at windowp[x+z] during a previous iteration. Also, you're checking the x+z<width, but you're not checking that x-z>=0.
David
Mcmount
20th April 2012, 06:37
Hi,
I uploaded sample jpg image as .zip, couldn't upload image formats.
I use one pixel offset to get rid of line where offset happens (example image,rightmost). If I don't offset I just get this unwanted line.
Without second iteration the result is the middle one in the image.
Yes, I need to do checking for x-z>0 also
As you can see, the aliasing problem is big. Another issue is that I don't think I'm exiting from the code nicely, becouse if I call same displace.dll twice in .avs with same input mask, it crashes. I can avoid this only by defining 2 separate masks, like;
my mask is image in YV12
maskL=image.converttorgb32
maskR=image.converttorgb32
displace(front,maskL,3)
displace(front,maskR,-3)
I can understand the example code mostly, but can't get it to work.
Any ideas?
Mcm
Gavino
20th April 2012, 08:36
Another issue is that I don't think I'm exiting from the code nicely, becouse if I call same displace.dll twice in .avs with same input mask, it crashes.
Post (or provide a link to) your entire plugin code.
Mcmount
20th April 2012, 15:41
Here is the link for the source, compiled dll and sample .avs (+the image I referred my second post);
http://doom9.media.toastpost.com/displace
Mcm
Gavino
20th April 2012, 16:11
Thanks for posting the code.
Another issue is that I don't think I'm exiting from the code nicely, becouse if I call same displace.dll twice in .avs with same input mask, it crashes.
I suspect this is because you are using window->GetWritePtr() to read the mask pixels. If the frame is not writable, this will return a null pointer, and it will not be writable if the same clip is used in two different filter instances. Since you don't actually write to the frame, you should use GetReadPtr() instead.
I don't know about your other problems as I still don't fully understand what your filter is meant to do.
Mcmount
20th April 2012, 16:29
Ok, thanks for that tip.
The whole idea of the filter is same what photoshop displacement filter is.
So foreground pixel x is moved to left (or right). How much - is taken from the luminance value of the mask at that same x position.
With this method you can create for example waving flag or moving water - effect. Cool thing is that you can control the movement by manipulating the mask.
Same technique is also used in some 3d-tv's. They use single 2d image and depth mask. The 2d image is displaced to left and right according the mask to get 3d-depth.
My problem is now the jaggered edges - otherwise it's kind of working.
If you have 3d vision kit or you can view 3d with eyes crossed, the .avs sample I created is actually 3d stereo, where depth is changing. When viewed crosseyed, the movement is not sideways - it's from back to front. For crosseyed, swap L and R to get it right.
Mcm
wonkey_monkey
20th April 2012, 18:01
Ah, now I see what you're doing. For a very simple fix for your aliasing problem, try scaling everything up x2 or x4 (horizontal only), apply your filter (with a similar multiplier on dev) and then resize back down. For a better fix, you need to subsample the pixels directly - calculating z as a float, not an int, and (for a simple bilinear subsample) using the fractional part as a weighting on the two pixels [x+(int)z] and [x+(int)z+1].
Input pixels: abcdef...
If x==3 (d) and z=0.5, the output pixel would be d*(1-z)+e*z=d*0.5+e*0.5
If x==2 (c) and z=0.25, the output pixel would be c*(1-z)*d*z=c*0.75+d*0.25
I use one pixel offset to get rid of line where offset happens (example image,rightmost). If I don't offset I just get this unwanted line.
Ultimately you would probably want to investigate bicubic or spline resampling.
I've got a sneaking suspicion that using framep[x]=framep[x-z-1] makes more sense in this case. In general, though, these things are usually done by writing to sequential output pixels, so in that sense I feel that your "second iteration" should really be your "first iteration" (writing to framep[x] with the appropriate input pixel at each step).
David
Mcmount
20th April 2012, 18:42
Thank you very much for exellent tips !
I'll start to investigate subsampling, as vertically stretching will be slow for 720p or 1080p material.
Got rid of the crash problem also, error was window->GetWritePtr().
Mcm
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.