View Full Version : (fast ?) Rotation plugin
Fizick
30th October 2007, 19:34
I developed and released new simple Rotate plugin.
Rotate plugin makes frames rotation on any given angle.
It may be used for perspective correction of amateur films or for special effect. Avisynth internal functions TurnLeft and TurnRight can rotate image on 90 degrees only. The Rotate plugin is faster than Zoom plugin and produces better quality images (IMO). Implemented Alan Paeth's method of bitmap rotation by means of 3 shears. Pixel (linear) interpolation is used at every shear. Size (scale) and aspect ratio of source picture are preserved.
Based on rotation code from:
http://treskunov.net/anton/Software/doc/fast_and_high_quality_true_color_bitmap_rotation_function.html
Syntax and parameters of version 1.1:
Rotate (clip, float "angle", int "width", int "height", int "color")
first parameter is the source clip.
angle is rotation angle in degrees clock wise. Default 0.
width and height is size of destination output image. Default 0 is to be equal to input clip size.
color is background color of part of clip. Integer or hex or global color constant like color_gray (see colors_rgb.avsi). Default 0 (color_black).
Color formats: RGB32 (fast MMX), YV12 (not optimized)
IMO, rotation filter should be Avisynth internal filter, but I am not sure about implementation :)
Speed and bug reports are welcome as well as algo discussion.
IanB
30th October 2007, 23:36
A wayback link for Tobin Fricke, Rotation by Shearing (http://web.archive.org/web/20040627185405/http://splorg.org/people/tobin/projects/israel/projects/paeth/rotation_by_shearing.html) (Damn domain name site gobblers :mad: )
Very nice find! Neat project! It's only BiLinear but it is a very sound start.
MfA
31st October 2007, 04:05
Memory access pattern on the vertical shear is nasty, but on something as simple as this who cares. Michael Unser has a paper on how accurate this approach can be compared to direct 2D interpolation (probably more than good enough most of the time).
http://bigwww.epfl.ch/publications/unser9502.pdf
Fizick
31st October 2007, 06:24
Some confusing with current version: YV12 rotation produce different (a little shifted) results from RGB32. Some reason is rotation direction change. Probably bug with center of rotation. I am not sure what is right.
Imagemagic avisynth port immaavs has rotate fuction, but it does not work for me.
There are many other good projects :)
http://www.leptonica.com/rotation.html
IanB
31st October 2007, 06:40
Direct 2D is very hard to MMX well, especially for higher order interpolation. Avery's VDub rotater is really devious. This offers a separable solution :D
And this triple shear implementation has heaps of room for improvement. i.e. get rid of the 90, 180 & 270 pre-rotates and adjust the core routine to work for all rotates (or do 4 core engines). Jazz the horizontal mmx code to do 2 or 4 pixels per loop. Jazz the the vertical MMX code to process across the image instead of down (I estimate any vertical code I wrote would be faster than the horizontal particularly for planar, in which case change the main code to be shear-V, shear-H, shear-V). Junk the width and height options and always output maximal size, this loses all the edge testing code in the inner loops, if really required just do as an implicit Crop on the output.
To improve accuracy, the multipoint interpolation could be stolen from the resizer core. Also shear-1 could output 16bit intermediate, shear-2 could process 16bit and shear-3 could process 16bit and finally output 8bit.
@Fizick,
To test the rotate doA=Last
Rotate(30.0)
Rotate(30.0)
Rotate(30.0)
TurnRight()
Subtract(A)A=Last
Rotate(-30.0)
Rotate(-30.0)
Rotate(-30.0)
TurnLeft()
Subtract(A)And at the boundary extremesA=Last
Rotate(45.0)
Rotate(45.0)
TurnRight()
Subtract(A)A=Last
Rotate(-45.0)
Rotate(-45.0)
TurnLeft()
Subtract(A)
hanfrunz
31st October 2007, 12:37
nice plugin!
May it also possible to use a modern GPU to do rotation?
regards,
hanfrunz
Fizick
31st October 2007, 15:22
There are also EffectsMany plugin by VCMohan
http://avisynth.org/vcmohan/EffectsMany/EffectRotation.html
its is even slower (I do not see some sourcecode) Zoom,
but has nice options set.
ARDA
31st October 2007, 20:55
First of all once more thanks for this contribution
You can find most of vcmohan's sources at:
http://avisynth.org/vcmohan/index.html
You should look for them in EffectsMany and TransAll
Relative to the simplest rotation case 180(no resize needed)
I have already implemented (Rotate180) for RGB32, YUY2 and YV12 mmx,isse and sse2
and a plain code for RGB24
Source Code and dll: http://www.iespana.es/Ardaversions/ROTATES_151.7z
You can follow in this thread http://forum.doom9.org/showthread.php?t=121066
This work was mainly intended to study write combining techniques and working
in place when algo and avisynth conditions were appropiate. You can find
a L2 cache size detection code used to choose when using non temporal instruccions.
It is not a fully finished work but I hope you can find something usefull from it.
Once more thanks
ARDA
Fizick
1st November 2007, 05:48
I discover, that used formulas are not precise (rounding to integer pixel). Weight of first pixel is not correct.
That is why the origin (center) or rotation is not stable.
may be sombody (Mfa) knows the correct reference article?
MfA
1st November 2007, 17:43
Don't have the original paper ... but once you have the decomposition into shears I don't really see why you need more information.
First shear : x' = x - tan (theta/2) * y
Second shear : y' = y + sin(theta) * x
Third shear : x' = x - tan (theta/2) * y
Everything else follows from that.
Netpbm and Freeimage implement the algorithm too BTW.
Fizick
1st November 2007, 18:44
I know formulas. I say about implementation.
I need more info because of I am lazy and I do not want calculate myself precise (float) offsets of center and corners (pixels) after every step.
I found codes for pixel pecision only (i say about position of origin of rotation). It is simple.
Pixels are discrete, shears are not.
I know how to do first shear correctly (i implement it in prepared next version).
But next steps parameters must be changed too and unclear for me how.
:)
Anyway, Shear may be useful Avisynth function too.
Archimedes
14th November 2007, 01:07
Nice plugin. I'm using it for image editing with AviSynth (http://forum.gleitz.info/showthread.php?t=33835). ;-)
mikeytown2
2nd July 2008, 10:35
Using 1.3 & 2.5.8 RC2
On frame 125 I get an Access Violation error with this script in MPC and AvsP.
ColorBars().Trim(0,200)
Animate(0,200, "Rotater" ,0.0, 360.0)
Function Rotater(clip c, float x)
{
c.Rotate_Rotate(x)
Subtitle(String(x))
}
Problem seems to be with an angle of 225
YV12 seems to have even more problems.
Fizick
2nd July 2008, 19:01
bug with angle=225 is confirmed.
Fixed in v.1.3.1
mikeytown2
2nd July 2008, 20:32
Thanks for fixing that! I have an example for YV12 that goes green and crashes on frame 206
ColorBars().Trim(0,999).ConvertToYV12()
Animate(0,999, "Rotater" ,0.0, 360.0)
Function Rotater(clip c, float x)
{
c.Rotate_Rotate(x)
Subtitle(String(x))
}
YV12 Problem Areas:
105.785358 <= Angle >= 074.214642
254.214638 >= Angle <= 285.785354
15.7853 from 90 and 270 are the problem areas
Fizick
25th July 2008, 20:20
fixed stupid bug with YV12 in v.1.3.2
mikeytown2
25th July 2008, 21:13
Thanks again for fixing the YV12 bug!
I have a feature request... Any chance of being able to specify the center of rotation (x,y)?
vcmohan
26th July 2008, 08:23
Rotation in EffectsMany plugin has the facility to specify center of rotation.
There are also EffectsMany plugin by VCMohan
http://avisynth.org/vcmohan/EffectsMany/EffectRotation.html
its is even slower.
It was speeded up a bit a few months back, though I did not do any bench mark..
mikeytown2
26th July 2008, 21:35
@vcmohan any chance of changing some of the int inputs into floats (rotation,x,y)?
I did a comparison of the different rotation plugin's for AviSynth a little while back
http://forum.doom9.org/showthread.php?p=1146653#post1146653
I didn't know about Fizick's Rotate plugin when i did that test. Fizick's Rotate plugin had the best speed/quality trade off; HQ and still fast.
I am currently looking into rotation plugin's for developing this transition script further...
http://forum.doom9.org/showthread.php?p=1157561#post1157561
Thanks for all the hard work both of you guys do!
vcmohan
27th July 2008, 10:29
@vcmohan any chance of changing some of the int inputs into floats (rotation,x,y)?
Now EffectRotation function of EffectsMany plugin accepts angle in float format. I do not presently thinking of changing the center coordinates x and y also to float. It probably will entail almost complete recoding.
Gavino
27th July 2008, 18:10
I do not presently thinking of changing the center coordinates x and y also to float. It probably will entail almost complete recoding.
I'm surprised to hear that - I would have naively expected it to work internally in floating point anyway. Clearly then, it's more sophisticated than that.
As a workaround, could rotation about an arbitrary center point (x, y) be achieved as follows? :
- use the fractional crop feature of the resizers to shift (x, y) in the image to the nearest integral point (x', y');
- apply the rotation about (x', y')
- reverse the shift
If this approach is valid, it could be done in a script wrapper by the user, or even built into the plugin itself if you think it is useful.
vcmohan
29th July 2008, 04:10
Yes it works on floats internally. But I use my this rotation helper function in several of my other pieces of software and changing this may render others disfunctional. Thats the reason I had the objection.
On second thoughts I will try to make a different helper for this effectrotation as soon as I get time. As I am using only bilinear interpolation, possibly I will change it to bicubic to improve quality. The speed will suffer. Is this worth all the trouble? Where exactly you need rotation axis at fractional pixel values?
The other approaches you suggest are feasible but as they involve one additional interpolation the quality is likely to suffer.
mikeytown2
29th July 2008, 09:25
I was going along with Gavino, I thought it would have been fairly easy to do. Subpixel (x,y) precision is always nice to have, but if its too much of a pain don't worry about it. I don't have a specific need for it; i could see that if someone used animate, it would be nice to have float precision.
Any chance that you could select the resizer function, have a speed/quality variable? like 0-2, 0 being Nearest Neighbor, 1 bilinear, 2 bicubic.
pandy
29th July 2008, 09:56
Any chance that you could select the resizer function, have a speed/quality variable? like 0-2, 0 being Nearest Neighbor, 1 bilinear, 2 bicubic.
Simply resize (x2, x4, x8 etc) video before rotation (at this stage i prefer PointResize) then do rotation and resize video back with prefered resize algorithm.
vcmohan
30th July 2008, 13:44
I was going along with Gavino, I thought it would have been fairly easy to do. Subpixel (x,y) precision is always nice to have.
There are various issues while dealing with positive and negative values internally. Since my plugin accepts rotation center to be anywhere in frame (or outside also with certain restrictions) some complications arise. However I started work on it.
Any chance that you could select the resizer function, have a speed/quality variable? like 0-2, 0 being Nearest Neighbor, 1 bilinear, 2 bicubic.
It should be possible. Most likely I will take it out of EffectsMany and make it a separate plugin.
I am curious. How much precision in the rotation axis is really required? 0.5, 0.25? or any arbitrary precision?
Fizick
30th July 2008, 21:12
i have shift, zoom and rotation engine in my Depan plugin (up to bicubic), but it is slow and uglyest code I ever wrote. :)
So I made attempt to rewrote it.
mikeytown2
30th July 2008, 21:41
What are the chances of one of these rotate code bases going into the avisynth core? I think it's one of the fundamental effects that you can do to an image/video so it wouldn't be out of place if it did go in. I have no idea how that process takes place, but I do believe a rotate function does belong in the core. Following Gimp, positive rotation would be clockwise.
You could have named functions just like resize
PointRotate
BilinearRotate
BicubicRotate
ect..
@vcmohan I really don't see a need for anything more then 1/2 pixel, but if if you can have arbitrary precision like in the resize's crop option then that is always a plus; limiting what can be done codewise is not always the best idea. Gimp's UI limits center x/y to int's unless you type it in; it also allows the center to be out of bounds of the image.
vcmohan
3rd August 2008, 16:10
Please see the post Spinner (http://forum.doom9.org/showthread.php?t=140019) in the usage section.
PeaceAnt
29th November 2008, 16:41
hello,
how about source and destination PAR parameters?
pozdrawiam
Fizick
30th November 2008, 12:57
source and destination PAR parameters are OK.
PeaceAnt
1st December 2008, 11:00
i work on PAL Widescreen (anamorphic) clips so when i want to rotate i must do something like:
lanczosresize(1024,576).Rotate(-45).lanczosresize(720,576)
or is in your filter a PAR correction parameter?
http://img224.imageshack.us/img224/1997/par1vg9.jpg
without and with PAR correction
pozdrawiam
IanB
1st December 2008, 13:32
The fast triple shear algorithm assumes square pixels, so this filter cannot be made to directly compensate for PAR.
Mohan's version uses the slower direct 2d interpolation, for that algorithm PAR compensation would be possible.
Hi, great plug-in. If one rotates an image & expands it, I think the new width & height that will fit the rotated image is given by h2 = round( w*sin(a)+h*cos(a) ) and w2 = round( w*cos(a)+h*sin(a) ), maybe one could just choose false or true to expand the image to this size
Sometimes I also get an CAVISynthStream system exception access violation at ... reading from ...
when specifying values for the new width & height. I get this error often ih the new width & height are larger than h2/w2 I mentioned in my last post. Does the new width/height have to be divisible by 2 or 4 or something like that?
Ivar
Terrachild
30th August 2009, 03:50
If I use Rotate, it works fine for the entire file, but if I do this:
"Rotate(angle = 10 ,endangle = 180)", it doesn't gradually change the rotation angle.
This "Rotate(angle = 10 ,start = 20, end = 100, endangle = 180)", also doesn't gradually rotate the frames. It does rotate the frames starting at 20 and ending at 100 though. So I know it is partially working.
Thanks for the help,
...anyone....anyone?
Fizick
9th September 2009, 21:19
Terrachild, fixed in new v1.3.3
tin3tin
10th September 2009, 18:39
I wonder if the Zoom plugin could benefit of this rotation code by somehow replacing the rotation calculations?
mikeytown2
11th September 2009, 09:19
@tin3tin
I considered incorporating a separate rotate plugin (like Fizick's) for KBE() (http://forum.doom9.org/showthread.php?t=135776) but decide against it last year. So that almost became a complete replacement for Zoom() (http://forum.doom9.org/showthread.php?t=49429)
tin3tin
11th September 2009, 14:36
Zoom is offers al lot of posibilities with 20 optional keyframes and such - but the quality and speed could be better - so the question is if this rotation code more or less could be liftet into Zoom?
Gavino
11th September 2009, 23:44
Zoom is offers al lot of posibilities with 20 optional keyframes and such
Not sure what you're referring to here. Perhaps that you can pass in a Spline expression giving intermediate parameter values? But that is not limited to 20.
If that's what you mean, note that you can do the same thing with any filter (including Rotate) by using Spline inside ScriptClip.
tin3tin
12th September 2009, 00:22
Oh; you're right it wasn't a limitation in Zoom, but apparently an Avisynth limitation of 60 arguments:
http://forum.doom9.org/showthread.php?p=595331#post595331
Gavino
12th September 2009, 00:35
That limitation was removed at least as far back as Avisynth 2.57.
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.