Skip to main content
Participant
June 2, 2022
Question

Autofit / Autoscale expression to comp

  • June 2, 2022
  • 2 replies
  • 946 views

I've created these expressions:

// Autofit & Autoscale expression

//Anchor property expression:
//center anchorpoint
s=sourceRectAtTime(); 
[s.left+s.width/2,s.top+s.height/2];

//Position property expression:
//!!! Manually set position x and y to 0 so position = [0,0,0] !!!
//original compsize
org_x = 1920;
org_y = 1080;

//create precentage correction:
corrx = (thisComp.width / org_x) * 100;
corry = (thisComp.height / org_y) * 100;

var cw = thisComp.width/2;
var ch = thisComp.height/2;
lw = thisLayer.sourceRectAtTime(time).width;
lh = thisLayer.sourceRectAtTime(time).height;

//apply position but with a correction based on original comp size...
mx = (transform.position[0]) * (corrx/100);
my = (transform.position[1]) * (corry/100);

//center position
x = thisComp.width/2;
y = thisComp.height/2;

[x + mx,y + my];

//Scale property expression:
//Two options scale to fit or fit to comp: 
scaletofit = true;

var lw = thisLayer.width;
var lh = thisLayer.height;
var cw = thisComp.width;
var ch = thisComp.height;

//which is bigger x or y?
x = ch/lh*100;
y = cw/lw*100;

function testaspect(x,y,scaletofit){
	check = (lw/100) * x;
	
	if (scaletofit){
		if (check < cw) x = y;
		else y = x;
	} else {
		if (check > cw) x = y;
		else y = x;
	}
		
	return [x,y];
}

if (cw < ch){
	// Comp widht is smaller Comp height;	
	out = testaspect(x,y,scaletofit);
} else if (cw > ch) {
	// Comp widht is bigger Comp height;	
	out = testaspect(x,y,scaletofit);
} else {
	// Comp widht is Comp height;	
	out = testaspect(x,y,scaletofit);		
}


//allow custom scale
mw = value[0];
mh = value[1];

[out[0] * (mw/100),out[1] * (mh/100)]


Next what I'm trying to accomplish is have:
1. A Point Controller Effect applied to the layer. 
2. Add a Transform Effect to the layer or add this expression to the transform property but with the Transform Effect it becomes more modular...  
3. Add an expression to the position of that Transform Effect that takes the Point Controller Effect into account...

var lw = thisLayer.width;
var lh = thisLayer.height;
var cw = thisComp.width;
var ch = thisComp.height;

scalex = cw/lw;
scaley = ch/lh;

//x = (cw/2) - thisLayer.sourceRectAtTime(time).width/2 * scalex;
//y = (ch/2) - (thisLayer.sourceRectAtTime(time).height/2 * scaley);


centerx = thisLayer.sourceRectAtTime(time).width/2 * scalex;
centery = thisLayer.sourceRectAtTime(time).height/2 * scaley;

//This is the point effect with a correction:
//Tried to use toComp() or fromComp() or toWorld() or fromWorld() but still need to figure out what the differences are...

cx = effect("sweetspotcorrection")("Point")[0] * scalex;
cy = effect("sweetspotcorrection")("Point")[1] * scaley;

cx = centerx / cx  * centerx/2
cy = centery / cy * centery/2

x = ch/lh*100;
y = cw/lw*100;

function testaspect(x,y){
	check = (lw/100) * x;
	
	if (check < cw) true;
	else false;
	
}

cx = cx * 1
cy = cy * 1

//These things seem to fix some of the issues in some occasions...
//if (lh > ch) cy = cy / 4
//if (lw > cw && cw < ch) cx = cx * 4	

if (cw < ch){
	// Comp widht is smaller Comp height;	
	out = testaspect(x,y);
	
	if (out) [0,cy]
	else [cx,0]
	
} else if (cw > ch) {
	// Comp widht is bigger Comp height;	
	out = testaspect(x,y);
	
	if (out) [0,cy]
	else [cx,cy]
} else {
	// Comp widht is Comp height;	
	out = testaspect(x,y);
	
	if (out) [0,cy]
	else [cx,0]

}


I think I'm close but if someone like @Dan Ebberts   might have a look?

This topic has been closed for replies.

2 replies

Community Expert
June 3, 2022

sourceRectAtTime() does not work on footage layers and it does not take into account a stroke on a shape layer. The function only works perfectly on Text layers so that part of your expression is basically meaningless for anything but a text layer.

 

I don't have time to dig into the rest of the expressions but I think you are way overcomplicating things. The easiest way to compensate for scale is to multiply a value by .01. If you shift the anchor point, you shift the layer position in the comp frame. 

 

I'm also not completely clear on exactly what you are trying to accomplish. I have a bunch of text animation presets that line up multiple text layers with shape layer backgrounds and position them in the frame. Some even move them in and out of the frame. 

 

I have similar expressions for footage layers. Just position the layer where you want it to rest and this Animation Preset will fly the layer in, bounce to a stop, then drop it out of the frame. Maybe it will give you some ideas.

 

Here's the code:

sif = effect("slideIn Frames")("Slider");
sof= effect("slideOut Frames")("Slider");
// find in and out pointOfInterest
stime = time - inPoint;
inTime = sif * thisComp.frameDuration;
	if (effect("Match SI SO")("Checkbox") == 0) {
	outTime = sof * thisComp.frameDuration;
	}
	else if (effect("Match SI SO")("Checkbox") == 1) {
	outTime = inTime;
	}
// Fix  layer size when scaled
sf = scale - [100, 100];
xSize = width + (width * sf[0]/100);
ySize = height + (height * sf[1]/100);
realSize = [xSize, ySize];
// Set Positions
spx = 0 - realSize[0] + realSize[0]/2 ;
rstx = value [0];
rsty = value[1];
epy = thisComp.height + realSize[1] - realSize[1]/2;
// create movement 
freq = effect("bounce Frequency")("Slider");
        amplitude = effect("bounce Amplitude")("Slider");
        decay = effect("bounce Decay")("Slider");
    posCos = Math.abs(Math.cos(freq*time*2*Math.PI));
	nt = time-inPoint;
    y = amplitude*posCos/Math.exp(decay*nt);
moveIn = Math.min(linear(stime,0,inTime,spx  ,rstx-y));
moveOut = Math.min(easeIn(time,outPoint - outTime,outPoint - thisComp.frameDuration,rsty ,epy));
[moveIn, moveOut]

I have obviously added Expression Controllers to the layer.

Participant
June 17, 2022

Thanks @Rick Gerard & @Roland Kahlenberg 
I'm now looking at clamp and the anchor point... 

//Scale expression:
var lw = thisLayer.width;
var lh = thisLayer.height;
var cw = thisComp.width;
var ch = thisComp.height;
x = ch/lh*100;
y = cw/lw*100;
function test(x,y){
	check = (lw/100) * x;
	
	if (check < cw) x = y;
	else y = x;
		
	return [x,y];
}
if (cw < ch){
	// Comp widht is smaller Comp height;	
	out = test(x,y);
} else if (cw > ch) {
	// Comp widht is bigger Comp height;	
	out = test(x,y);
} else {
	// Comp widht is Comp height;	
	out = test(x,y);		
}
mw = value[0];
mh = value[0];
[out[0] * (mw/100),out[1] * (mh/100)]
//position property
org_x = 1920;
org_y = 1080;
corrx = (thisComp.width / org_x) * 100;
corry = (thisComp.height / org_y) * 100;
mx = (transform.position[0]) * (corrx/100);
my = (transform.position[1]) * (corry/100);
x = thisComp.width/2;
y = thisComp.height/2;
[x + mx,y + my];
//Anchor point

//to do: 
//find away to calculate 
//The min & max of x & y that the image is allowed to be "moved"
//For this I need to have the comp.width & height times the 100 - scaled value (to make it fit into the comp) subtracted with the "sweetspot" defined by the Anchor Point...
// if (comp.width >= layer.width && comp.height >= layer.height) this will be true:

xo = thisLayer.width/2;
yo = thisLayer.height/2;
//[xo,yo];

x = clamp(transform.anchorPoint[0], xo, xo);
y = clamp(transform.anchorPoint[1], yo, yo);
[x,y]

// else we need to find the min / max of either x & y...

 I created a screenrecording.
Hopefully you'll see what I'm trying to achieve.

Roland Kahlenberg
Legend
June 17, 2022

Oh my, I've gone through a couple of hundred of layers with code, over a couple of thousand of lines of code - also Responsive MoGraph stuff. It's not fun. LOL
I think already have an idea what you want to achieve. Where we disagree is the approach and algorithm. I'd still go the PPro route with AutoReframe or if it's going to be done in AE, then an algorithm has to be decided. 

My thoughts are to allow the user to select/define the are of interest. And if the area of interest moves across the image as part of natural or camera movement, then you've require motion tracking. Only after that will you be able to define the size of the result as selected by the user. There is also the case for using AI to enlarge the image as and when required and it'll be useful in the entire scheme of things. YOu may also want to allowthe user to synthesize the edges with something like CC Repetile or to create traditional or even more conventionallly designed borders to make your work easier. 

This Q is not ideal for a forum question due to its complexity - hopefully you get lucky and someone has done something similar or is able to more quickly provide a more direct solution. On my end, unfortunately, I have more Qs than answers. 

 

Very Advanced After Effects Training | Adaptive &amp; Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Participant
June 2, 2022

Basically the question is, is it possible?
Any links or comments are most welcome thanks.

Roland Kahlenberg
Legend
June 2, 2022

What exactly are you trying to achieve? Autofit/AutoScale a Video Layer? Or is it something else?

Very Advanced After Effects Training | Adaptive &amp; Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Participant
June 2, 2022

Autofit/AutoScale a Video or Image but also to have a point of interest or "sweetspot" i like to call it.