www.jetdv.com Forum Index Edward Troxel
Vegas Scripting and Newsletters
Home of Excalibur and Montage Magic
 
 FAQ   Search   Memberlist   Usergroups   Register   Profile 
 Log in to check your private messagesLog in to check your private messages   Log inLog in 

Apply a Pan / Crop preset

 
Post new topic   Reply to topic    www.jetdv.com Forum Index -> Scripting FAQ
View previous topic :: View next topic  
Author Message
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Thu Aug 23, 2007 12:58 am    Post subject: Apply a Pan / Crop preset Reply with quote

I've reviewed lots of posts here regarding pan / crop, aspect ratio etc but I'm still pretty much in the dark about applying a pan / crop preset (or, in my case, width x height if its easier) via a script.

Here's what I'm trying to do in "English"
Code:
Work on the selected events only
do while ???
  Look at the event
    if it is an image //not sure if there is a distinction between video and stills
    do case
      Case size is 360 x 480
        apply pan / crop preset "360 x 480" or resize to 360 x 530
      case size is 655 x 480
        apply pan crop preset "655x480" or resize to 725 x 480
      case horizonatal size is less than 400
        apply pan / crop preset "something else"
    end case
    next event
Loop
TaDa! 


I downloaded a bunch of scripts from a link in this post and checked out matchaspect.js. It looks like it might have the basis of what I need.

I'm happy to have a crack at it, but thought maybe someone already has done this or something close.
Back to top
View user's profile Send private message
Edward Troxel
Site Admin


Joined: 14 Jul 2004
Posts: 5475

PostPosted: Thu Aug 23, 2007 1:03 pm    Post subject: Reply with quote

Is what you're wanting to do reset the image to its original size? If yes, that's what the "Logo Resize" tool in Excalibur does - it will take an image added to Vegas and reset it back to the original size instead of "stretched" to fill the screen.

The first step is to do the "Match Aspect" which you've seen in the other script. After doing that, I run it through this routine:

Code:
VideoEvent videoEvent   = trackEvent as VideoEvent;   
VideoMotionKeyframes keyframes = videoEvent.VideoMotion.Keyframes;;
int cKeyframes = keyframes.Count;
for (int jj = cKeyframes - 1; jj >= 0 ; jj--)
{
   VideoMotionKeyframe thisKeyframe = keyframes[jj] as VideoMotionKeyframe;

   float dWidth = Math.Abs(thisKeyframe.TopRight.X   - thisKeyframe.TopLeft.X);
   float dHeight = Math.Abs(thisKeyframe.BottomLeft.Y - thisKeyframe.TopLeft.Y);;

   float pwid = dWidth / scrWidth * 100;
   ScaleKeyframe(thisKeyframe, pwid);
}


"ScaleKeyframe" is another routine I've written that will scale it the specified percentage and rotate it if needed.

Removing the rotation (and the same removed above), this should work for you:

Code:
public void ScaleKeyframe(VideoMotionKeyframe keyframe, float szChange)
{
   float cWidth = (1 / (szChange / 100));
   float cHeight = (1 / (szChange / 100));
   
   VideoMotionVertex bounds = new VideoMotionVertex(cWidth, cHeight);
   
   keyframe.ScaleBy(bounds);
}
Back to top
View user's profile Send private message Send e-mail
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Thu Aug 23, 2007 10:21 pm    Post subject: Reply with quote

Thanks Edward.

What I'm doing is this.

Dumping several thousand jpgs on the timeline, each with 0.5 sec duration.

Some of these jpgs are 655 x 480 and some are 360 x 480. They are dumped on the timeline in the date order the picture was taken. Pictures of my daughter from birth until now.

What I've done until now is eyeballed each picture and done a manual pan crop to get the detail within the 4:3 safe border area. I can then use Paste Event Attributes.

After messing with the script to add borders, I figured I could maybe do the pan / crop with a script. It would save me a lot of time!

I think that I can figure it out based on the matchaspect script and your post, I just need to get a chunk of time longer than 15 minutes!

While on the topic of stills, what's your view on the idea of resizing pics from 720x480 to 655x480 due to pixel aspect ratio?
Back to top
View user's profile Send private message
Edward Troxel
Site Admin


Joined: 14 Jul 2004
Posts: 5475

PostPosted: Fri Aug 24, 2007 1:14 pm    Post subject: Reply with quote

fredfillis wrote:
While on the topic of stills, what's your view on the idea of resizing pics from 720x480 to 655x480 due to pixel aspect ratio?


I expect that to happen because it is normal. 720x480 are STRETCHED pixels - the computer/photo editor is not. So Vegas compensates for you.

You CAN get a 720x480 still from Vegas if you wish, though. Simply click the button beside the save snapshot button which copies to the clipboard instead. Now go to your paint program and paste. This will paste a 720x480 image but it should look odd as the pixel sizes are not being properly compensated for.
Back to top
View user's profile Send private message Send e-mail
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Sun Aug 26, 2007 8:24 pm    Post subject: Reply with quote

Edward, I've got it working for what I need.

I wrote what made sense. Now I'll go back and have a look at your code snippets and see if I can streamline things a bit.

I'll post what I've got so far later today. Not very elegant but it works.

Note that all my jpgs were cropped to 655 x 480 or 360 x 480 before they were dropped on the timeline. What I'm trying to do is blow them up to 725 x 480 and 360 x 530 to stay within the safe areas on 4:3 where the project is set to 720x480.

And now that I've written that down, it makes my head hurt Shocked Why would a 655 x 480 image occupy the entire screen whereas a 725 x 480 image appear smaller and stay within the safe area?

Cheers!
Back to top
View user's profile Send private message
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Mon Aug 27, 2007 12:36 am    Post subject: Reply with quote

Ok, here is what I have. It works but comes up with an error at the end.

AutoPanAmber.js( 98 ) : Variable 'xBig' might not be initialized

Can't figure that out because it only happens at the end!

Code:
// "Set selection to certain width x height size based on current width and center.
//Modified from matchaspect.js as posted at http://s92274348.onlinehome.us/vegas.html
// No selection = ALL

import System.Windows.Forms;
import Sony.Vegas;

var zero : int = 0;

function GetSelectionCount (mediaType)
{
    var cTracks   = Vegas.Project.Tracks.Count;
    var cSelected = zero;
    var ii;
   
    for (ii = zero; ii < cTracks; ii ++)
    {
        var track = Vegas.Project.Tracks[ii];
       
        if (track.MediaType == mediaType)
        {           
            var eventEnum : Enumerator = new Enumerator(track.Events);
       
            while ( ! eventEnum.atEnd() )
            {           
                if (eventEnum.item().Selected)
                {               
                    cSelected ++;       
                }
               
                eventEnum.moveNext();                           
            }
        }                                 
    }
   
    return cSelected;
}

function GetActiveMediaStream (trackEvent : TrackEvent)
{
    try
    {
        if ( ! trackEvent.ActiveTake.IsValid())
        {
            throw "empty or invalid take";
        }               
       
        var media = Vegas.Project.MediaPool.Find (trackEvent.ActiveTake.MediaPath);
       
        if (null == media)
        {
            throw "missing media";
        }
       
        var mediaStream = media.Streams.GetItemByMediaType (MediaType.Video, trackEvent.ActiveTake.StreamIndex);       
       
        return mediaStream;
    }
    catch (e)
    {
        //MessageBox.Show(e);
        return null;
    }   
}

function MatchOutputAspect (keyframe : VideoMotionKeyframe, dMediaPixelAspect : double, dAspectOut : double)
{
    var keyframeSave = keyframe;
   var xBig, xSmall = false
       
    try
    {
        var rotation = keyframe.Rotation;   
       
        // undo rotation so that we can get at correct aspect ratio.
        //
        keyframe.RotateBy (-rotation);

        var dWidth         = Math.abs(keyframe.TopRight.X   - keyframe.TopLeft.X);
        var dHeight        = Math.abs(keyframe.BottomLeft.Y - keyframe.TopLeft.Y);
        var dCurrentAspect = dMediaPixelAspect * dWidth / dHeight;
        var centerY        = keyframe.Center.Y;
        var centerX        = keyframe.Center.X;
      if(centerX>251)
      {
         var xBig=true;
         var xSmall=false;
      }
      if(centerX<252)
      {
         var xBig=false;
         var xSmall=true;
      }
      
        var bounds = new VideoMotionBounds(keyframe.TopLeft, keyframe.TopRight, keyframe.BottomRight, keyframe.BottomLeft);
      

      if(xBig==true) //This is the offending line 96
      {
         var centerX=327.5;
         var dWidth=725/2;
         var dHeight = 480;
            bounds.TopLeft.X     = centerX-dWidth;
            bounds.TopRight.X    = centerX+dWidth;
            bounds.BottomLeft.X  = centerX-dWidth;
            bounds.BottomRight.X = centerX+dWidth;
            bounds.TopLeft.Y     = 0;
            bounds.TopRight.Y    = 0;
            bounds.BottomLeft.Y  = dHeight;
            bounds.BottomRight.Y = dHeight;
      }
      if(xSmall==true)
      {
         var centerY=240
         var centerX=180;
         var dWidth=360/2;
         var dHeight = 530/2;
            bounds.TopLeft.X     = centerX-dWidth;
            bounds.TopRight.X    = centerX+dWidth;
            bounds.BottomLeft.X  = centerX-dWidth;
            bounds.BottomRight.X = centerX+dWidth;
            bounds.TopLeft.Y     = centerY-dHeight;
            bounds.TopRight.Y    = centerY-dHeight;
            bounds.BottomLeft.Y  = centerY+dHeight;
            bounds.BottomRight.Y = centerY+dHeight;
      }
      // set it to new bounds
      var xBig, xSmall=false
 
      keyframe.Bounds = bounds;
       
        // restore rotation.       
        keyframe.RotateBy (rotation);
       
    }
    catch (e)
    {
        // restore original settings on error
        keyframe = keyframeSave;
        //MessageBox.Show("MatchOuput: " + e);
    }   
}


var dWidthProject  = Vegas.Project.Video.Width;
var dHeightProject = Vegas.Project.Video.Height;
var dPixelAspect   = Vegas.Project.Video.PixelAspectRatio;
var dAspect        = dPixelAspect * dWidthProject / dHeightProject;
var cSelected      = GetSelectionCount (MediaType.Video);


var cTracks = Vegas.Project.Tracks.Count;
var ii;

for (ii = zero; ii < cTracks; ii ++)
{
    var track   = Vegas.Project.Tracks[ii];
   
    if (! track.IsVideo())
    {
        continue;
    }
   
    var eventEnum : Enumerator = new Enumerator(track.Events);       
   
    while ( ! eventEnum.atEnd() )
    {
        var trackEvent : TrackEvent = eventEnum.item();                                   
       
        if ( !cSelected || trackEvent.Selected )
        {                                           
            var mediaStream = GetActiveMediaStream (trackEvent);               
           
            if (mediaStream)
            {                                   
                var videoStream = VideoStream (mediaStream);
                   
                var dMediaPixelAspect = videoStream.PixelAspectRatio;
                var videoEvent        = VideoEvent(eventEnum.item());   
                var keyframes         = videoEvent.VideoMotion.Keyframes;
               
                var cKeyframes = keyframes.Count;
                var jj;
               
                for (jj = zero; jj < cKeyframes; jj ++)
                {
                    MatchOutputAspect (keyframes[jj], dMediaPixelAspect, dAspect);                                                                     
                }
            }
        }
       
        eventEnum.moveNext();
    }
}


Vegas.UpdateUI();

Back to top
View user's profile Send private message
Edward Troxel
Site Admin


Joined: 14 Jul 2004
Posts: 5475

PostPosted: Mon Aug 27, 2007 1:37 am    Post subject: Reply with quote

You're creating variables inside the IF statements. When you do that, it is possible that the variable may never be set. Instead, create the variables outside of the IF and then assign new values inside the IF.
Back to top
View user's profile Send private message Send e-mail
Edward Troxel
Site Admin


Joined: 14 Jul 2004
Posts: 5475

PostPosted: Mon Aug 27, 2007 2:22 am    Post subject: Reply with quote

Here's one example:

Code:
      if(centerX>251)
      {
         var xBig=true;
         var xSmall=false;
      }
      if(centerX<252)
      {
         var xBig=false;
         var xSmall=true;
      }
 


The "var" should NOT be in these statments. You've already defined the variable in this routine and should not be redefining them. In fact, that entire routine could use some work. This revision is untested but try something like this instead:

Code:
function MatchOutputAspect (keyframe : VideoMotionKeyframe, dMediaPixelAspect : double, dAspectOut : double)
{
    var keyframeSave = keyframe;
    var xBig = false
       
    try
    {
        var rotation = keyframe.Rotation;   
       
        // undo rotation so that we can get at correct aspect ratio.
        //
        keyframe.RotateBy (-rotation);

        var dWidth         = Math.abs(keyframe.TopRight.X   - keyframe.TopLeft.X);
        var dHeight        = Math.abs(keyframe.BottomLeft.Y - keyframe.TopLeft.Y);
        var dCurrentAspect = dMediaPixelAspect * dWidth / dHeight;
        var centerY        = keyframe.Center.Y;
        var centerX        = keyframe.Center.X;
      xBig = false;
      if(centerX>251)
      {
         xBig=true;
      }
       
        var bounds = new VideoMotionBounds(keyframe.TopLeft, keyframe.TopRight, keyframe.BottomRight, keyframe.BottomLeft);
       

      if(xBig==true)
      {
         var centerX=327.5;
         var dWidth=725/2;
         var dHeight = 480;
            bounds.TopLeft.X     = centerX-dWidth;
            bounds.TopRight.X    = centerX+dWidth;
            bounds.BottomLeft.X  = centerX-dWidth;
            bounds.BottomRight.X = centerX+dWidth;
            bounds.TopLeft.Y     = 0;
            bounds.TopRight.Y    = 0;
            bounds.BottomLeft.Y  = dHeight;
            bounds.BottomRight.Y = dHeight;
      }
      else
      {
         var centerY=240
         var centerX=180;
         var dWidth=360/2;
         var dHeight = 530/2;
            bounds.TopLeft.X     = centerX-dWidth;
            bounds.TopRight.X    = centerX+dWidth;
            bounds.BottomLeft.X  = centerX-dWidth;
            bounds.BottomRight.X = centerX+dWidth;
            bounds.TopLeft.Y     = centerY-dHeight;
            bounds.TopRight.Y    = centerY-dHeight;
            bounds.BottomLeft.Y  = centerY+dHeight;
            bounds.BottomRight.Y = centerY+dHeight;
      }
 
      keyframe.Bounds = bounds;
       
        // restore rotation.       
        keyframe.RotateBy (rotation);
       
    }
    catch (e)
    {
        // restore original settings on error
        keyframe = keyframeSave;
        //MessageBox.Show("MatchOuput: " + e);
    }   
}
Back to top
View user's profile Send private message Send e-mail
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Mon Aug 27, 2007 3:40 am    Post subject: Reply with quote

Thanks for the tips Edward. I'm not surprised that the routine could "use some work" Laughing

I guess I'm not 100% clear on the if ... var thing.

Based on the snippet you posted, there are still var declarations inside the if (xBig==true) for example. Is that just an oversight?

I left some rubbish in there (xBig and xSmall) because I was using messagebox to see when I got into the right If statements. For whatever reason, I seemed to be getting into both the "big" and "small" statements in sequence.

In addition, I did not (yet) take into consideration the case where width and/or height might be negative values. If that happens, the rotation gets flipped when the script is run.

Cheers!
Back to top
View user's profile Send private message
Edward Troxel
Site Admin


Joined: 14 Jul 2004
Posts: 5475

PostPosted: Mon Aug 27, 2007 1:35 pm    Post subject: Reply with quote

No. Those are variables that are being declared and then directly used inside the IF statement but NOWHERE ELSE. That's the key - they're not used anywhere else! For anything that is use outside the IF statement, it must also be declared outside the IF statement.
Back to top
View user's profile Send private message Send e-mail
fredfillis



Joined: 19 Aug 2007
Posts: 27
Location: Washington DC via Australia!

PostPosted: Mon Aug 27, 2007 6:21 pm    Post subject: Reply with quote

Thanks Edward. Your "untested" code worked without a hitch.

Now I have to restrain myself from spending all my time learning more about scripting and spending on my video projects instead!

Hopefully, I'll do some of each. Very Happy
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    www.jetdv.com Forum Index -> Scripting FAQ All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB 2.0.11 © 2001, 2002 phpBB Group