Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER for Video Editing/Mangling

Reply
 
Thread Tools Display Modes
Old 11-12-2018, 07:58 AM   #1
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default Is blur, bokeh, gaussian blur in Video processor possible?

I asked myself,

if Reapers video processor is capable of any kind of blur or noise. Now that we have masks it would be awesome if even the simplest "out of focus", blur, noise etc. could be done. This would allow to take the same video once untouched and once blurred to interchange it via masks with different shapes.

Just an idea. And I'm curious by nature.
Eliseat is offline   Reply With Quote
Old 11-12-2018, 09:13 AM   #2
karbomusic
Human being with feelings
 
karbomusic's Avatar
 
Join Date: May 2009
Posts: 29,260
Default

"Lens blur" as they call it in Photoshop, Davinci Resolve etc? I think that's a fairly complex thing to do based on my use of it in PS and Resolve since actual lens components are usually emulated (blade number, blade shape and so on).

I'd imagine something generic is possible but that's about all I know but making it pleasing vs just making it will matter. With at least some background in photography, bokeh is a big deal to me in general. I have a couple of lenses that I consider best of the best for the quality of their bokeh - and a few other lenses who's strengths are anything but good bokeh, aka the bokeh is ugly and sickly looking.

That's also why I mostly use DSLRs for my video work, because I get to use my bokeh-friendly lenses for subject isolation and the finer visual qualities it offers, I really hate (sometimes) cameras with fixed high apertures and endless DOF. That said, I can get by with Gaussian if I have to but bokeh is almost always better.
__________________
Music is what feelings sound like.
karbomusic is offline   Reply With Quote
Old 11-12-2018, 03:32 PM   #3
EpicSounds
Human being with feelings
 
EpicSounds's Avatar
 
Join Date: Jul 2009
Posts: 7,568
Default

I too would really like to have this even if it's very basic. the only thing roughly similar right now is the pixelate preset.

In one of my Q&A videos that I edited using Resolve. I tracked an oval mask around my face, feathered it and added a bit of blur to everything outside the mask. IIRC it was extremely cpu intense and took ages to track and render. A nice effect but not worth the effort IMO.
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
EpicSounds is offline   Reply With Quote
Old 11-12-2018, 03:41 PM   #4
karbomusic
Human being with feelings
 
karbomusic's Avatar
 
Join Date: May 2009
Posts: 29,260
Default

Quote:
Originally Posted by EpicSounds View Post
I too would really like to have this even if it's very basic. the only thing roughly similar right now is the pixelate preset.

In one of my Q&A videos that I edited using Resolve. I tracked an oval mask around my face, feathered it and added a bit of blur to everything outside the mask. IIRC it was extremely cpu intense and took ages to track and render. A nice effect but not worth the effort IMO.
Basic is fine, just make it pretty as the only thing worse than no bokeh, is ugly bokeh.

Did you use the stock free blur or the paid blur in Resolve? Just curious. I just upgraded to Resolve Studio over the weekend because I found that they restrict GPU usage in the free version - which also gave me the lens blur and a few other niceties as well.
__________________
Music is what feelings sound like.
karbomusic is offline   Reply With Quote
Old 11-13-2018, 07:51 AM   #5
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Quote:
Originally Posted by EpicSounds View Post
I too would really like to have this even if it's very basic. the only thing roughly similar right now is the pixelate preset.

In one of my Q&A videos that I edited using Resolve. I tracked an oval mask around my face, feathered it and added a bit of blur to everything outside the mask. IIRC it was extremely cpu intense and took ages to track and render. A nice effect but not worth the effort IMO.
Bokeh really is a cpu intense process. That's true. It isn't possible to preview it in a DAW like Reaper. But simple Gaussian blur could be handled like in VLC. In VLCs video effects is a blur effect with sigma parameter and it runs nearly in real time for 1280x720 mp4 with a high bitrate. At least at my slowly laptop.
Noise or grain is also possible and would be a big deal for video projects as its a good method for matching different video sources. Question was and is if Reapers Video processor eel is capable for doing something like this.
Eliseat is offline   Reply With Quote
Old 11-13-2018, 06:44 PM   #6
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Atm it's really not a matter of is it pretty. To the best of my knowledge gfx_evalrect() can only convolve in x-direction so useful filters aren't possible.
Unless you resort to slight hacks like convolve in x, rotate the image 90°, convolve again and rotate back but that's a bit silly. Which of course I did anyways lol. This really ugly and really costly 1st order lowpass is only supposed to be a proof of concept, maybe somebody else knows better:
Code:
// simple 1st order lowpass
//@param1:weight 'weight' 0.1 0 1 0.5 0.001

in=0;
oldCS=colorspace;

gfx_dest = xWs = gfx_img_resize(xWs,project_w,project_h);
gfx_blit(in);

w=project_w;
h=project_h;

colorspace='RGBA';
#code="
(_1 -= 1) < 0 ? (
  _1=w-1;
  _2=0; _3=0; _4=0; _5=0;
);
r=_2+weight*(r-_2); _2=r;    // weight*r + (1-weight)*lr
g=_3+weight*(g-_3); _3=g;
b=_4+weight*(b-_4); _4=b;
a=_5+weight*(a-_5); _5=a;
";

// convolve in x
gfx_evalrect(0,0,w,h, #code);

// rotate 90°
gfx_dest = rotWs1 = gfx_img_resize(rotWs1,w,w,-1);
gfx_rotoblit(xWs,$pi/2);

// convolve in y (now x)
gfx_evalrect(0,0,w,w, #code);

// rotate back
gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,w,-1);
gfx_rotoblit(rotWs1,-$pi/2);

//gfx_img_resize(-1,w,h);
gfx_dest=-1;
gfx_blit(rotWs2);

colorspace=oldCS;

Last edited by wwwmaze; 11-15-2018 at 11:48 AM. Reason: maybe in the end it's not so silly?
wwwmaze is offline   Reply With Quote
Old 11-13-2018, 07:21 PM   #7
karbomusic
Human being with feelings
 
karbomusic's Avatar
 
Join Date: May 2009
Posts: 29,260
Default

Quote:
Originally Posted by wwwmaze View Post
Atm it's really not a matter of is it pretty.
For Gaussian blur, pretty is irrelevant, and just trying to figure things out, pretty is also irrelevant but... if creating "lens blur/bokeh", it's completely useless if the bokeh is ugly - because that is what bokeh is about... "the aesthetic quality of out of focus elements from a lens". I can create examples from a real camera to demonstrate the difference if that helps in the future.

However, I misread the original post where they were just wanting to be able to do blur period, which has plenty of value on it's own. Not trying to be overly pedantic, it's just the difference between the two matters a bit.
__________________
Music is what feelings sound like.

Last edited by karbomusic; 11-13-2018 at 07:31 PM.
karbomusic is offline   Reply With Quote
Old 11-14-2018, 01:04 AM   #8
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

wwwmaze,

you are just crazy! What the heck?

Its like: "Can we fly to the moon?"
Wwwmaze, waving from the moon: "Yes, we can!"

That is just amazing. And you think its ugly? Take a look at this:

This gif shows your preset thru a mask I made in Photoshop. Simple but cool!


This gif shows the exact same setting expect I used a pre rendered video from Adobe Premiere. It uses the standard blur preset. Isn't it amazing how nice your preset is?


Many, many thanks!
Eliseat is offline   Reply With Quote
Old 11-14-2018, 01:39 AM   #9
EpicSounds
Human being with feelings
 
EpicSounds's Avatar
 
Join Date: Jul 2009
Posts: 7,568
Default

yep real costly but concept is proven. Blur transitions have been on my wishlist for a while and this is now possible, even if it does take 25% of my i7's power. thanks

My quick test here, with weight automated

https://youtu.be/BrkuqUf97Sk
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
EpicSounds is offline   Reply With Quote
Old 11-14-2018, 03:01 AM   #10
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Yes, it needs a lot of power. But blur is essential. And I had to wait with Adobe Premiere too.

Here are two examples of animating "weight" vs. blend over from video a to blurred video a. You clearly see how the low pass comes in in the second case. Looks a bit like a 70s softsex movie.







I'm still impressed. Really nice one.
Eliseat is offline   Reply With Quote
Old 11-14-2018, 03:25 PM   #11
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Hehe awesome demos guys, yes it's the definition of a CPU-Hog, isn't it?

A huge factor is that I'm using RGBA colorspace.
If I use "YV12", which I'm absolutely not familiar with, CPU goes down by roughly a quarter here.
The flip side is that I'm currently getting strange black stripy things using that. I must be doing something wrong...
wwwmaze is offline   Reply With Quote
Old 11-15-2018, 07:13 AM   #12
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Awesome!

Here's a simplified version that operates in YV12, and adjusts the blur/weight knob to give a nice feeling curve:
Code:
// simple blur, YV12
//@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001

in=0;

colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

weight = weight_parm^.25;
uvweight= sqr(weight);
code="
(_1 -= 1) < 0 ? (
  _1=eval_w*.5-1;
  _2=y1; _3=y3; _4=u; _5=v;
);
y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2));
y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4));
_4=(u+=uvweight*(_4-u));
_5=(v+=uvweight*(_5-v));
";

weight>.00001 ? (
  extrasz=min((log(0.5)/log(weight) + 2),w/4)&0xfffc; // phase adjustment size
  
  // copy to expanded work buffer (to fix phase)
  gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w+extrasz,h); 
  gfx_blit(in,0,0,0,w,h,0,0,w,h);
  gfx_fillrect(w,0,extrasz,h);
  
  // convolve in x
  eval_w = w+extrasz;
  gfx_evalrect(0,0,w+extrasz,h, code);
  
  // rotate to expanded vertical work buffer 
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h+extrasz,w);
  gfx_deltablit(rotWs2,0,0,h,w, extrasz*.5,0, 0,1,1,0,0,0);
  gfx_fillrect(h,0,extrasz,w);
  
  // convolve in y (now x)
  eval_w = h+extrasz;
  gfx_evalrect(0,0,h+extrasz,w, code);
  
  // rotate back to output framebuffer
  gfx_dest = -1;
  gfx_deltablit(rotWs1,0,0,w,h,extrasz*.5,0, 0,1,1,0,0,0);
 
) : gfx_blit(in);
Mind if I add this as a preset?

(edit: bugfixed and simplified a little -- there are some artifacts on the left edge, though, hm).

Last edited by Justin; 11-15-2018 at 08:06 AM.
Justin is offline   Reply With Quote
Old 11-15-2018, 07:46 AM   #13
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Works great. Preview mostly in real time. Rendering HD in 0.7 real time h624, quality 95%.

Very nice. And thanks to all who made this happen.
Eliseat is offline   Reply With Quote
Old 11-15-2018, 08:07 AM   #14
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Edited the above post again -- it now preserves phase (position) and has a slightly better knob curve
Justin is offline   Reply With Quote
Old 11-15-2018, 09:00 AM   #15
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Hi,

I guess you moved the shifting to the right side. I have no idea if this can be fixed. But it only shows with extreme settings. So ...



But this is now possible. Blur blending. Its one of the things that I really missed. Thanks again.
Eliseat is offline   Reply With Quote
Old 11-15-2018, 09:16 AM   #16
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by Eliseat View Post
Hi,

I guess you moved the shifting to the right side. I have no idea if this can be fixed. But it only shows with extreme settings. So ...



But this is now possible. Blur blending. Its one of the things that I really missed. Thanks again.
That's awesome! Yeah, the shifting to the right side is not avoidable due to the algorithm used, to fix it would require a lot more CPU (given the way evalrect() is implemented, boo).

Last edited by Justin; 11-15-2018 at 09:25 AM.
Justin is offline   Reply With Quote
Old 11-15-2018, 09:37 AM   #17
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Here's a version that shifts down/right and up/left simultaneously, though at the cost of twice the CPU use:
Code:
// blur, YV12
//@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001
//@param2:bidir 'bidirectional' 1 0 1 0 1

in=0;

colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

weight = weight_parm ^.25;
uvweight= sqr(weight);
code="
(_1 -= 1) < 0 ? (
  _1=eval_w*.5-1;
  _2=y1; _3=y3; _4=u; _5=v;
);
y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2));
y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4));
_4=(u+=uvweight*(_4-u));
_5=(v+=uvweight*(_5-v));
";

pass=0;
weight>.00001 ? loop(bidir?2:1,
  gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h); 
  pass==0 ? gfx_blit(in,0,0,0,w,h,0,0,w,h)
        : gfx_deltablit(in,0,0,w,h,w-1,h-1,-1,0,0,-1);
  
  // convolve in x
  eval_w = w;
  gfx_evalrect(0,0,w,h, code);
  
  // rotate to expanded vertical work buffer 
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(rotWs2,0,0,h,w, 0,0, 0,1,1,0,0,0);
   
  // convolve in y (now x)
  eval_w = h;
  gfx_evalrect(0,0,h,w, code);
  
  // rotate back to output framebuffer
  gfx_dest = -1;
  gfx_a=pass?0.5:1;
  pass==0? gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0):
    gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0);
  gfx_a=1;
  pass+=1;
) : gfx_blit(in);
(Edit: made it optional)

Last edited by Justin; 11-15-2018 at 01:26 PM.
Justin is offline   Reply With Quote
Old 11-15-2018, 10:24 AM   #18
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Yes, that fixed it.

It looks now even more amazing as it reminds a bit of defocusing a lens objective. (At least a bit.) Pretty cool. And the CPU usage isn't as high as expected. I could even preview it in real time with only some lags. Thank you.

Eliseat is offline   Reply With Quote
Old 11-15-2018, 11:38 AM   #19
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Cool thank you for making it linear phase Justin! And for making it much lighter
Going to look at the code now. Had some problems rotating the workspace and probably overdone it a bit so I'm interested to see what you've done.
wwwmaze is offline   Reply With Quote
Old 11-15-2018, 01:43 PM   #20
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Quote:
Originally Posted by wwwmaze View Post
Cool thank you for making it linear phase Justin! And for making it much lighter
Going to look at the code now. Had some problems rotating the workspace and probably overdone it a bit so I'm interested to see what you've done.
gfx_rotoblit() has some bad behaviors (and we're sort of stuck with them), so gfx_deltablit() is a big help

Here's a slightly improved version (it avoids creating second extra buffer on single-pass mode):
Code:
// Blur
//@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001
//@param2:bidir 'bidirectional' 1 0 1 0 1

in=0;

colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

weight = weight_parm ^.25;
uvweight= sqr(weight);
code="
(_1 -= 1) < 0 ? (
  _1=eval_w*.5-1;
  _2=y1; _3=y3; _4=u; _5=v;
);
y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2));
y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4));
_4=(u+=uvweight*(_4-u));
_5=(v+=uvweight*(_5-v));
";

pass=0;
weight>.00001 ? loop(bidir?2:1,
  pass ? (
    // second pass, use a copy rotated 180
    gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h);
    gfx_deltablit(in,0,0,w,h,w-1,h-1,-1,0,0,-1);
  ) : (
    gfx_blit(in,0,0,0,w,h,0,0,w,h);
  );

  // convolve in x
  eval_w = w;
  gfx_evalrect(0,0,w,h, code);

  // rotate to vertical work buffer
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0);

  // convolve in y (now x)
  eval_w = h;
  gfx_evalrect(0,0,h,w, code);

  // rotate back to output framebuffer
  gfx_dest = -1;
  gfx_a=pass?0.5:1;
  pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0):
       gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0);
  gfx_a=1;
  pass+=1;
) : gfx_blit(in);
Justin is offline   Reply With Quote
Old 11-15-2018, 04:05 PM   #21
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

It's now more than half as CPU intensive (on single pass) than my try and doesn't have that huge shift. Awesome work!

Quote:
Originally Posted by Justin View Post
gfx_rotoblit() has some bad behaviors (and we're sort of stuck with them), so gfx_deltablit() is a big help
gfx_deltablit() was one of the last 2 mysteries of video processor for me, thanks for pushing me into that direction. So s and t are really only the x- and y-coordinates of the source? I.e. dsdx set to 2 means 2 steps of s results in 1 step of x in the destination buffer/image. Cool!
wwwmaze is offline   Reply With Quote
Old 11-15-2018, 04:56 PM   #22
EpicSounds
Human being with feelings
 
EpicSounds's Avatar
 
Join Date: Jul 2009
Posts: 7,568
Default

so if we can blur then unsharp mask shouldn't be too far off right?
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
EpicSounds is offline   Reply With Quote
Old 11-15-2018, 08:49 PM   #23
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

OK one more -- this one looks extra good, allows you to control the ratio between vertical and horizontal, allows you to turn off diff l/r/u/d blurs, but is also pretty slow.

Code:
// Blur
//@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001
//@param2:weight_mod 'Y modifier' 1 .8 1.2 1.0 0.001
//@param4:want_l 'leftward' 1 0 1 0 1
//@param5:want_r 'rightward' 1 0 1 0 1
//@param6:want_u 'upward' 1 0 1 0 1
//@param7:want_d 'downward' 1 0 1 0 1

in=0;
colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

function rot(new_ang, dest, blur) local(lw,lh,ang) (
  gfx_dest=dest;
  ang = (new_ang+4-c_ang)&3;
  c_ang = new_ang&3;
  lw=(c_ang&1) ? h:w;
  lh=(c_ang&1) ? w:h;
  ang==0 ? gfx_blit(c_last,0, 0,0,lw,lh,0,0,lw,lh) :
  ang==1 ? gfx_deltablit(c_last, 0,0, lw,lh, 0,   lw-1,  0, -1,  1,  0) :
  ang==2 ? gfx_deltablit(c_last, 0,0, lw,lh, lw-1,lh-1, -1,  0,  0, -1):
  ang==3 ? gfx_deltablit(c_last, 0,0, lw,lh, lh-1,0,     0,  1, -1,  0);    
  blur ? (     
    weight= min(weight_parm*((c_ang&1) ? weight_mod : 1/weight_mod),1) ^.25;
    uvweight=max(min(weight*5.2-3.7,.94),0); // experimentally derived
    eval_w = lw; gfx_evalrect(0,0,lw,lh, sprintf(#,"
      (_1 -= 1) < 0 ? (
        _1=eval_w*.5-1;
        _2=y1; _3=y3; _4=u; _5=v;
      );
      y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2));
      y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4));
      %s", uvweight > 0.000001 ? "
        _4=(u+=uvweight*(_4-u));
        _5=(v+=uvweight*(_5-v));
        " : "")
    ); 
  );
  c_last=dest; 
);

c_ang=0;
c_last=in; 
weight_parm>.00001? ( 
  want_l ? rot(2, -1, 1);
  want_d ? rot(3, img3 = gfx_img_resize(img3,h,w),1);  
  want_u ? rot(1, img2 = gfx_img_resize(img2,h,w),1);
  want_r || c_last==-1 ? rot(0, c_last==-1 ? (img1 = gfx_img_resize(img1,w,h)) : -1,want_r);
);
c_last != -1 ? rot(0, -1, 0);

Last edited by Justin; 11-15-2018 at 09:18 PM. Reason: tweaked the UV filtering coefficient some to look better (for one bit of test material anyway)
Justin is offline   Reply With Quote
Old 11-16-2018, 12:18 AM   #24
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

This is actually bonus and very handy for a special challenge: Motion blur of a camera movement. If you have a video and want to pan it, this would be the perfect solution to let it look more natural as you can follow the direction.

But this one really sucks the energy out of my Laptop.

Anyway. Very nice. Thanks.
Eliseat is offline   Reply With Quote
Old 11-16-2018, 12:51 AM   #25
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

Here are the examples:

Without motion blur its hard to follow the movement. It looks unnatural.




With (fake) motion blur it looks like a real movement. Its a bit over done to show the effect more clearly.



Of course you have to take care at the speed of the movement. As you can see I peaked the blur at the steepest movement curve. And I chose the leftward parameter at max. level.



And one last thing: This last preset with the separate 4 directions is nearly impossible to preview but for some reason it renders more quickly than expected.
Eliseat is offline   Reply With Quote
Old 11-18-2018, 05:24 PM   #26
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Hey all,

I went and implemented this Gaussian filter (3rd-order recursive) approximation: https://www.researchgate.net/publica...aussian_filter

Alas it's again working in 'RGBA' colorspace as I still have no clue about 'YV12' and can't fathom what Justin is doing with these YV12 vars in gfx_evalrect().
So it's again a bit CPU intensive.

The good thing is, since it's recursive, it should be equal bad (or good after some optimization) for every value of sigma, unlike some other Gaussian implementations.

I'm interested to hear how it looks compared to other Gaussian blurs.

@Justin: I noticed that you blend the 2 passes together in your filters. I just work on the main framebuffer after the 1st pass which (I think) has the same effect of correcting the phase.

Code:
Edit: updated version, see post 37 below

Last edited by wwwmaze; 11-23-2018 at 10:20 AM.
wwwmaze is offline   Reply With Quote
Old 11-18-2018, 07:32 PM   #27
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

heh nice, though maybe you should look at the newer YV12 ones I did (where there's not really two passes, instead it just blurs the output of the previous passes)

You could also probably speed the RGBA version up a bit by not bothering with alpha
Justin is offline   Reply With Quote
Old 11-18-2018, 07:47 PM   #28
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

YV12 version:

Code:
// Recursive Gaussian Blur
//@param1:sigma 'Sigma' 10 0.5 50 25 0.1
//@param2:bidir 'bidirectional' 1 0 1 0 1

in=0;

initDone==0 ? (lsigma=-1; initDone=1;);

// coeffs
lsigma!=sigma ? (
  q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330;
  b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3;
  b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3;
  b2 = -1.4281*q^2 - 1.26661*q^3;
  b3 = 0.422205*q^3;
  BB = 1-(b1+b2+b3)/b0;
  b1b0=b1/b0;
  b2b0=b2/b0;
  b3b0=b3/b0;
  lsigma=sigma;
);

colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

code="
(_1 -= 1) < 0 ? (
  _1=eval_w-1;
  _31=_21=_11=0; _32=_22=_12=0; _33=_23=_13=128; _34=_24=_14=128;
);
y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11;
y2=BB*y2 + b1b0*y1 + b2b0*_21 +b3b0*_31; _31=_21; _21=y1; _11=y2;
y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12;
y4=BB*y4 + b1b0*y3 + b2b0*_22 +b3b0*_32; _32=_22; _22=y3; _12=y4;

u=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=u;
v=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34; _34=_24; _24=_14; _14=v;
";


gfx_dest=-1;
pass=0;
loop(bidir?2:1,
  pass ? (
    // second pass, use main buffer rotated 180
    gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h);
    gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1);
  ) : (
    gfx_blit(in,0,0,0,w,h,0,0,w,h);
  );

  // convolve in x
  eval_w = w/2;
  gfx_evalrect(0,0,w,h, code);

  // rotate to vertical work buffer
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0);

  // convolve in y (now x)
  eval_w = h/2;
  gfx_evalrect(0,0,h,w, code);

  // rotate back to output framebuffer
  gfx_dest = -1;
  pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0):
       gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0);
  pass+=1;
);
Quick note of explanation:

In YV12 mode, the image is processed with 4 pixels at a time (apologies for inaccuracies in terminology):
  • y1 = top row, left luminance
  • y2 = top row, right luminance
  • y3 = bottom row, left luminance
  • y4 = bottom row, right luminance
  • u = U for 4 pixels
  • v = V for 4 pixels
U/V are sort of a vector defining the color and saturation, roughly speaking (not exactly), with values of 128 meaning centered (zero). So their filter states need to get initialized to 128.

So this filter runs the two Y rows as separate filters (avoiding some extra shuffling), and U/V filters separate (The U/V filters probably should have different coefficients since they are running at half the rate).

Both this filter and the simpler one-pole filter have some weird effects on the color/saturation. It might actually make more sense to convert the U/V values to polar coordinates and filter that, but that would be excruciatingly slow.

Last edited by Justin; 11-18-2018 at 07:57 PM.
Justin is offline   Reply With Quote
Old 11-19-2018, 01:28 AM   #29
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

First of all: I worship you wizards of code really hard.

But now lets get to the Gaussian blur challenge. As you can see, the directional feature does not really work. It just changes the direction from NW to SE. Adobe somehow managed to let the pixels stay in place as in Justins blur preset with four directions.

Here is a comparison of three variations of one clip:

First is the rgba version from wwwmaze which was hardly playable in arrange preview. Rendering speed 0.2 real time




Second version is Justins YV12 version. Also hardly watchable in preview. But 0.4 real time rendering. As Justin mentioned. For some reason the colors are bleeding out the more you increase the blur.




And finally the Premiere pro rendering. The final blur amount is just a guess. Preview was also not possible. Rendering seemed as fast or a little bit faster then Reapers.




Many thanks for your work. Its just amazing to see what is possible. Gaussian blur is a beautiful effect with lots of possibilities. Reaper video becomes more and more professional. I really love it. (If there wouldn't be so much guessing for cropping, panning etc.)

Greetings from Cologne
Eli
Eliseat is offline   Reply With Quote
Old 11-19-2018, 01:43 AM   #30
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

In a side by side comparison its clearly visible that the rgba version nearly nails it. Though the Premiere pro version seems to get a bit brighter. But this could be a an optical illusion because of the dark frame becoming thicker in the other versions. The YV12 version is at the moment not comparable because of the fading colors but it would be a really step forward in rendering time.

As much as I love Photoshop I really don't like Adobe. Its probably the most arrogant company in the world. So its even more welcome to have a rising alternative in one of their scopes.
Eliseat is offline   Reply With Quote
Old 11-19-2018, 09:59 AM   #31
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

One thing I have to ask. If I use a picture on one track, use its transparency to let the video beneath shining thru and then want to blur it to give the effect of a defocused leave above a video background it just blurs everything. Is it even possible to blur only the track input or does it always blur everything coming thru?

Its a bit confusing to me as Reapers video tracks sometimes don't act like tracks.

I will post an example later because my English isn't good enough to describe it properly.
Eliseat is offline   Reply With Quote
Old 11-19-2018, 02:20 PM   #32
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Quote:
Originally Posted by Justin View Post
YV12 version:
Quick note of explanation:

In YV12 mode, the image is processed with 4 pixels at a time (apologies for inaccuracies in terminology):
  • y1 = top row, left luminance
  • y2 = top row, right luminance
  • y3 = bottom row, left luminance
  • y4 = bottom row, right luminance
  • u = U for 4 pixels
  • v = V for 4 pixels
U/V are sort of a vector defining the color and saturation, roughly speaking (not exactly), with values of 128 meaning centered (zero). So their filter states need to get initialized to 128.

So this filter runs the two Y rows as separate filters (avoiding some extra shuffling), and U/V filters separate
Thanks Justin, that's a great explanation. Everything is crystal clear now.

Quote:
Originally Posted by Justin View Post
The U/V filters probably should have different coefficients since they are running at half the rate
Thanks for the YV12 blur! I see how that could be causing problems. I'm no expert so I need to (and going to) read into it.

Quote:
Originally Posted by Justin View Post
Both this filter and the simpler one-pole filter have some weird effects on the color/saturation. It might actually make more sense to convert the U/V values to polar coordinates and filter that, but that would be excruciatingly slow.
Since u and v are set to 128 (=zero saturation) at the border and the effect increases at higher sigmas I have a strong feeling that this may be caused by the problem above. I'll investigate further.

Last edited by wwwmaze; 11-19-2018 at 02:41 PM.
wwwmaze is offline   Reply With Quote
Old 11-19-2018, 02:39 PM   #33
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Quote:
Originally Posted by Eliseat View Post
As you can see, the directional feature does not really work. It just changes the direction from NW to SE. Adobe somehow managed to let the pixels stay in place as in Justins blur preset with four directions.
Thanks for the demos/tests Eli, again.
Concerning the shift, if you focus a single feature in the image it should stay in place (unlike the 1-directional blur) but I agree that black margin at SE is confusing so I should think about a way to remove it.

Quote:
Originally Posted by Eliseat View Post
Second version is Justins YV12 version. Also hardly watchable in preview. But 0.4 real time rendering. As Justin mentioned. For some reason the colors are bleeding out the more you increase the blur.
Yes, the conversion of the preset to YV12 colorspace is probably not yet complete (see also my answer to Justin).
wwwmaze is offline   Reply With Quote
Old 11-22-2018, 02:06 AM   #34
Skaven252
Human being with feelings
 
Join Date: Nov 2011
Posts: 143
Default

Awesome, incredible, thank you for the blurs!

This should make a high pass / unsharp mask (mix inverted blurred signal back to source, restore contrast) possible as well, like EpicSounds mentioned.

https://en.wikipedia.org/wiki/Unsharp_masking
Skaven252 is offline   Reply With Quote
Old 11-22-2018, 08:50 AM   #35
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

This is already possible per Selective Blender from wwmaze. Works in a limited way. Maybe it could be set up in one preset.

Keep it in mind.

The setup would be a folder with Selective Blender blend mode 4 and 100% video b. Inside a "track a" with the clean video and a "track b" with the same video but also a video processors with blur. "Track b" needs also a black and white filter, a contrast adjustment after the blur and finally a color invert.

Here an example with an increasing amount of blur. (But 0.1 real time render.)



Greetings
Eli
Eliseat is offline   Reply With Quote
Old 11-22-2018, 09:24 AM   #36
EpicSounds
Human being with feelings
 
EpicSounds's Avatar
 
Join Date: Jul 2009
Posts: 7,568
Default

I must have missed that one. That looks pretty good
__________________
REAPER Video Tutorials, Tips & Tricks and more at The REAPER Blog
EpicSounds is offline   Reply With Quote
Old 11-22-2018, 05:51 PM   #37
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

For the Gaussian blurs I think I managed to let the YV12 version work almost (not exactly, there are still minor color differences) like the RGBA version. I had to introduce some additional multi-add pairs though because I couldn't figure out how to modify the coefficients. So there's still room for optimization.

I also fixed the image borders for the bidirectional case.


RGBA version:
Code:
// Gaussian Blur RGBA
// v0.2
//@param1:sigma 'Sigma' 10 0.5 50 25 0.1
//@param2:bidir 'bidirectional' 1 0 1 0 1
//@param8:restore_cs 'preserve colorspace' 1 0 1 0 1

in=0;

initDone==0 ? (lsigma=-1; initDone=1;);

// coeffs
lsigma!=sigma ? (
  q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330;
  b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3;
  b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3;
  b2 = -1.4281*q^2 - 1.26661*q^3;
  b3 = 0.422205*q^3;
  BB = 1-(b1+b2+b3)/b0;
  b1b0=b1/b0;
  b2b0=b2/b0;
  b3b0=b3/b0;
  lsigma=sigma;
);

oldcs=colorspace;
colorspace='RGBA';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

code="
(_1 -= 1) < 0 ? (
  _1=eval_w-1;
  _31=_21=_11=r; _32=_22=_12=g; _33=_23=_13=b;
);
r=BB*r + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11; _11=r;    // r=BB*r + b1b0*lr + b2b0*llr +b3b0*lllr; lllr=llr; llr=lr; lr=r;
g=BB*g + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12; _12=g;
b=BB*b + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=b;
";

pass=0;
loop(bidir?2:1,
  pass ? (
    // second pass, use main buffer rotated 180
    gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h);
    gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1);
  ) : (
    gfx_blit(in,0,0,0,w,h,0,0,w,h);
  );

  // convolve in x
  eval_w = w;
  gfx_evalrect(0,0,w,h, code);

  // rotate to vertical work buffer
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0);

  // convolve in y (now x)
  eval_w = h;
  gfx_evalrect(0,0,h,w, code);

  // rotate back to output framebuffer
  gfx_dest = -1;
  pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0):
       gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0);
  pass+=1;
);

restore_cs && oldcs != colorspace ? colorspace=oldcs;
YV12 version:
Code:
// Gaussian Blur YV12
// v0.2
//@param1:sigma 'Sigma' 10 0.5 50 25 0.1
//@param2:bidir 'bidirectional' 1 0 1 0 1

in=0;

initDone==0 ? (lsigma=-1; initDone=1;);

// coeffs
lsigma!=sigma ? (
  q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330;
  b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3;
  b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3;
  b2 = -1.4281*q^2 - 1.26661*q^3;
  b3 = 0.422205*q^3;
  BB = 1-(b1+b2+b3)/b0;
  b1b0=b1/b0;
  b2b0=b2/b0;
  b3b0=b3/b0;
  lsigma=sigma;
);

colorspace='YV12';
input_info(in,w,h);
gfx_img_resize(-1,w,h);

code="
(_1 -= 1) < 0 ? (
  _1=eval_w-1;
  _31=_21=_11=y1; _32=_22=_12=y3; _33=_23=_13=u; _34=_24=_14=v;
);
y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31;
y2=BB*y2 + b1b0*y1 + b2b0*_11 +b3b0*_21; _31=_11; _21=y1; _11=y2;
y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32;
y4=BB*y4 + b1b0*y3 + b2b0*_12 +b3b0*_22; _32=_12; _22=y3; _12=y4;

_90=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33;
u=BB*u + b1b0*_90 + b2b0*_13 +b3b0*_23; _33=_13; _23=_90; _13=u;
_91=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34;
v=BB*v + b1b0*_91 + b2b0*_14 +b3b0*_24; _34=_14; _24=_91; _14=v;
";


gfx_dest=-1;
pass=0;
loop(bidir?2:1,
  pass ? (
    // second pass, use main buffer rotated 180
    gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h);
    gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1);
  ) : (
    gfx_blit(in,0,0,0,w,h,0,0,w,h);
  );

  // convolve in x
  eval_w = w/2;
  gfx_evalrect(0,0,w,h, code);

  // rotate to vertical work buffer
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0);

  // convolve in y (now x)
  eval_w = h/2;
  gfx_evalrect(0,0,h,w, code);

  // rotate back to output framebuffer
  gfx_dest = -1;
  pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0):
       gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0);
  pass+=1;
);
EDIT: oops I think the YV12 version now uses the same CPU resources?? so hmmm... not ideal

EDIT: updated versions with a bugfix see Justins posts below

Last edited by wwwmaze; 11-27-2018 at 08:30 AM.
wwwmaze is offline   Reply With Quote
Old 11-23-2018, 01:32 AM   #38
Eliseat
Human being with feelings
 
Eliseat's Avatar
 
Join Date: Mar 2018
Location: Cologne
Posts: 1,362
Default

INCREDIBLE!

This looks so awesome now.

Here is the obligatory test to show how great this works. It seems the YV12 version tends a bit more to saturation or green in lighter areas. But I would say that's a normal behavior as its a color conversion.

Take a look how beautiful this is: (despite the fact that i had to convert it into a gif )



Many thanks again.
Eliseat is offline   Reply With Quote
Old 11-23-2018, 10:30 AM   #39
wwwmaze
Human being with feelings
 
Join Date: Oct 2009
Posts: 99
Default

Cool I like lizards too
Quote:
Originally Posted by Eliseat View Post
It seems the YV12 version tends a bit more to saturation or green in lighter areas.
Yes, that's exactly what I was noticing too.

Many thanks also for starting the preset collection thread Eli. Very useful initiative! Imo this could easily be a sticky thread.
wwwmaze is offline   Reply With Quote
Old 11-25-2018, 07:15 PM   #40
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,721
Default

Here's a version that uses the native colorspace (YV12 or RGBA), rather than forcing a colorspace (colorspace conversion is quite slow by itself!)

Code:
// Gaussian Blur
// v0.2
//@param1:sigma 'Sigma' 10 0.5 50 25 0.1
//@param2:bidir 'bidirectional' 1 0 1 0 1

in=0;

initDone==0 ? (lsigma=-1; initDone=1;);

// coeffs
lsigma!=sigma ? (
  q = (0.5<=sigma && sigma <=2.5) ? 3.97156-4.14554*sqrt(1-0.26891*sigma) : 0.98711*sigma-0.96330;
  b0 = 1.57825 + 2.44413*q + 1.4281*q^2 + 0.422205*q^3;
  b1 = 2.44413*q + 2.85619*q^2 + 1.26661*q^3;
  b2 = -1.4281*q^2 - 1.26661*q^3;
  b3 = 0.422205*q^3;
  BB = 1-(b1+b2+b3)/b0;
  b1b0=b1/b0;
  b2b0=b2/b0;
  b3b0=b3/b0;
  lsigma=sigma;
);

colorspace!='RGBA' ? colorspace='YV12';

input_info(in,project_w,project_h);
w=project_w; h=project_h;

code=colorspace=='RGBA' ? "
(_1 -= 1) < 0 ? (
  _1=eval_w-1;
  _31=_21=_11=r; _32=_22=_12=g; _33=_23=_13=b;
);
r=BB*r + b1b0*_11 + b2b0*_21 +b3b0*_31; _31=_21; _21=_11; _11=r;
g=BB*g + b1b0*_12 + b2b0*_22 +b3b0*_32; _32=_22; _22=_12; _12=g;
b=BB*b + b1b0*_13 + b2b0*_23 +b3b0*_33; _33=_23; _23=_13; _13=b;
" : "
(_1 -= 1) < 0 ? (
  _1=eval_w*.5-1;
  _31=_21=_11=y1; _32=_22=_12=y3; _33=_23=_13=u; _34=_24=_14=v;
);
y1=BB*y1 + b1b0*_11 + b2b0*_21 +b3b0*_31;
y2=BB*y2 + b1b0*y1 + b2b0*_11 +b3b0*_21; _31=_11; _21=y1; _11=y2;
y3=BB*y3 + b1b0*_12 + b2b0*_22 +b3b0*_32;
y4=BB*y4 + b1b0*y3 + b2b0*_12 +b3b0*_22; _32=_12; _22=y3; _12=y4;

_90=BB*u + b1b0*_13 + b2b0*_23 +b3b0*_33;
u=BB*u + b1b0*_90 + b2b0*_13 +b3b0*_23; _33=_13; _23=_90; _13=u;
_91=BB*v + b1b0*_14 + b2b0*_24 +b3b0*_34;
v=BB*v + b1b0*_91 + b2b0*_14 +b3b0*_24; _34=_14; _24=_91; _14=v;
"
;

pass=0;
loop(bidir?2:1,
  pass ? (
    // second pass, use main buffer rotated 180
    gfx_dest = rotWs2 = gfx_img_resize(rotWs2,w,h);
    gfx_deltablit(-1,0,0,w,h,w-1,h-1,-1,0,0,-1);
  ) : (
    gfx_blit(in,0,0,0,w,h,0,0,w,h);
  );

  // convolve in x
  eval_w = w;
  gfx_evalrect(0,0,w,h, code);

  // rotate to vertical work buffer
  gfx_dest = rotWs1 = gfx_img_resize(rotWs1,h,w);
  gfx_deltablit(pass?rotWs2:-1,0,0,h,w, 0,0, 0,1,1,0,0,0);

  // convolve in y (now x)
  eval_w = h;
  gfx_evalrect(0,0,h,w, code);

  // rotate back to output framebuffer
  gfx_dest = -1;
  pass?gfx_deltablit(rotWs1,0,0,w,h,h-1,w-1, 0,-1,-1,0,0,0):
       gfx_deltablit(rotWs1,0,0,w,h,0,0, 0,1,1,0,0,0);
  pass+=1;
);
and here is the lower quality linear blur with the same multi-colorspace support:
Code:
// Blur (low quality)
//@param1:weight_parm 'blur amount' .5 0 .99 0.5 0.001
//@param2:weight_mod 'Y modifier' 1 .8 1.2 1.0 0.001
//@param4:want_l 'leftward' 1 0 1 0 1
//@param5:want_r 'rightward' 1 0 1 0 1
//@param6:want_u 'upward' 1 0 1 0 1
//@param7:want_d 'downward' 1 0 1 0 1

in=0;

colorspace!='RGBA' ? colorspace='YV12';
input_info(in,project_w,project_h);
w=project_w; h=project_h;

function rot(new_ang, dest, blur) local(lw,lh,ang) (
  gfx_dest=dest;
  ang = (new_ang+4-c_ang)&3;
  c_ang = new_ang&3;
  lw=(c_ang&1) ? h:w;
  lh=(c_ang&1) ? w:h;
  ang==0 ? gfx_blit(c_last,0, 0,0,lw,lh,0,0,lw,lh) :
  ang==1 ? gfx_deltablit(c_last, 0,0, lw,lh, 0,   lw-1,  0, -1,  1,  0) :
  ang==2 ? gfx_deltablit(c_last, 0,0, lw,lh, lw-1,lh-1, -1,  0,  0, -1):
  ang==3 ? gfx_deltablit(c_last, 0,0, lw,lh, lh-1,0,     0,  1, -1,  0);
  blur ? (
    weight= min(weight_parm*((c_ang&1) ? weight_mod : 1/weight_mod),1) ^.25;
    weight2 = sqr(weight);
    eval_w = lw; gfx_evalrect(0,0,lw,lh, 
      colorspace=='RGBA' ? "
        (_1 -= 1) < 0 ? (
          _1=eval_w-1;
          _2=r; _3=g; _4=b;
        );
        r+=weight*(_2-r); _2=r; g+=weight*(_3-g); _3=g; b+=weight*(_4-b); _4=b;     
      " : "
        (_1 -= 1) < 0 ? (
          _1=eval_w*.5-1;
          _2=y1; _3=y3; _4=u; _5=v;
        );
        y1+=weight*(_2-y1); _2=(y2+=weight*(y1-y2));
        y3+=weight*(_3-y3); _3=(y4+=weight*(y3-y4));
        _4=(u+=weight2*(_4-u));
        _5=(v+=weight2*(_5-v));
      "
    );
  );
  c_last=dest;
);

c_ang=0;
c_last=in;
weight_parm>.00001? (
  want_l ? rot(2, -1, 1);
  want_d ? rot(3, img3 = gfx_img_resize(img3,h,w),1);
  want_u ? rot(1, img2 = gfx_img_resize(img2,h,w),1);
  want_r || c_last==-1 ? rot(0, c_last==-1 ? (img1 = gfx_img_resize(img1,w,h)) : -1,want_r);
);
c_last != -1 ? rot(0, -1, 0);

Last edited by Justin; 11-25-2018 at 07:47 PM.
Justin is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 08:10 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.