Activity › Forums › Adobe After Effects Expressions › Is there a way to know the width and height of a layer similar to sourceRectAtTime?
-
Is there a way to know the width and height of a layer similar to sourceRectAtTime?
Posted by Mateo Baldasare on July 30, 2019 at 4:36 pmHi there!
I’ve been trying to figure this out for a while now and I wonder if it is actually possible through expressions.
I would like to know the resulting width and height of an image with an alpha channel (or that image inside a pre-comp), similarly as you would do with the expression for shape and text layers sourceRectAtTime().
I’ve tried with the sampleImage() expression, but that just gives me an average of the overall opacity.
Thanks!!
Filip Vandueren replied 2 years ago 6 Members · 17 Replies -
17 Replies
-
Tomas Bumbulevičius
July 30, 2019 at 6:02 pmHey Mateo,
what about simply width & height for a layer?
thisLayer.width
thisLayer.height
EDIT: I guess you are talking about the image, assuming that all the alpha around is part of it. Sorry! There is a good script called AutoCrop, which allows crop image without affecting any of its transformation props (if that helps)
Find out more:
After Effects Tutorials: motion design, expressions, scripting.
Boxer – Dynamic Text Boxes Template with a Live Preview -
Mateo Baldasare
July 30, 2019 at 7:07 pmThanks a lot, Tomas!
That really does the trick for the cropped image ????
I wonder if there is a workaround to do the same for a pre-comp (with the png image already cropped). I tried with the Collapse Transformations option checked and with the same expression, but it gives me the whole height or width (in this case 1920 by 1080).
Thanks again!
-
Malcolm Ricci
July 6, 2020 at 10:45 amHey guys,
By any chance do you know whether there is an expression that could be used instead of the Auto-Crop 2 script please?
I need it to be an expression as the project file is shared over multiple computers and some of them cannot have any scripts installed on them.
Thanks,
Malcolm -
Filip Vandueren
July 7, 2020 at 1:22 pmThere are methods, however they are very slow, the expression has to sample the pixels to determine where there is transparancy.
-
Filip Vandueren
July 7, 2020 at 2:16 pmThe best workaround I can think of is to include in your project a special Comp that is only 1 frame long, just as a helper/utility
(Size of the comp is not important, the layer can be larger than the comp)I’ll call the Comp “Sampler”
In that Comp you put the layer you want to know the exact dimension of.
Also a text-layer (“txt”) with this expression:
l=thisComp.layer("Layer 1/transp.psd"); // the layer you want to sample.
w=l.width;
h=l.height;s=[0,0,0,0];
for (x=0; (s[3]==0 &&x<=w); x++) s=l.sampleImage([x,h/2], radius = [0.5, h/2], postEffect = false, t = time);
leftEdge=x;s=[0,0,0,0];
for (x=w; (s[3]==0 &&x>=0); x--) s=l.sampleImage([x,h/2], radius = [0.5, h/2], postEffect = false, t = time);
rightEdge=x;s=[0,0,0,0];
for (y=0; (s[3]==0 &&y<=h); y++) s=l.sampleImage([w/2,y], radius = [w/2, 0.5], postEffect = false, t = time);
topEdge=y;s=[0,0,0,0];
for (y=h; (s[3]==0 &&y>=0); y--) s=l.sampleImage([w/2,y], radius = [w/2, 0.5], postEffect = false, t = time);
bottomEdge=y;pixelRect = {
top: topEdge,
left: leftEdge,
width: (rightEdge-leftEdge),
height: (bottomEdge-topEdge),
right: rightEdge,
bottom: bottomEdge,
center: [leftEdge + (rightEdge-leftEdge)/2 , topEdge + (bottomEdge-topEdge)/2]};
JSON.stringify(pixelRect);
(I’ve added some extra handy parameters that sourceRect doesn’t have, but might be handy)Now in the comps where you need the “pixelRect” of that footage, you call it like this:
pixelRect = JSON.parse(comp("sampler").layer("txt").text.sourceText.valueAtTime(0));
[pixelRect.width, pixelRect.height];
Probably there’s an even more optimal code for finding the edges, haven’t experimented with this yet. (a binary search algorithm perhaps)
I recommend running this in 16bit at least.
8bit will not be as precise because for speedsake, I’m sampling/averaging whole rows/columns at a time, and at 8bit, a very slight Alpha in a just few pixels might be rounded down to 0.Then again, you might want to experiment with a threshold that is a bit higher than the absolute s[2]==0 alpha-test I used, in the case of slight halo’s or keyed footage, it might be too strict, it depends on your footage.
Anyway.
The optimized/clever bit is that Because the “sampler”-comp is only 1 frame long, it won’t keep calculating and using valueAtTime(0) from within the other comps also ensures this:
the expression effectively gets cached in the other comp and doesn’t have to be recalculated.
=SpeedgainIf it’s impossible to make those extra comps, just adapt the expression without the JSON-bit, and live with the added rendertime of recalculating the alpha every frame.
-
Tomas Bumbulevičius
July 11, 2020 at 10:53 amHey Filip, thanks a lot for sharing, nicely done. I made a test comparison to inspect whether it works – and can confirm, it definitely does work as expected. Few notices:
1. Great idea about using extra comp as util to be handled – haven’t thought about it and thats definitely a workaround to have in mind, thank you!
2. Did you actually tried rendering the output and see how expression being affects computation? I haven’t tried that, but at least in the viewport, it seams a bit laggy, even with valueAtTime(0), as it is being recalculated and not actually stored IMO. Due to this fact, I would suggest for anyone, who are going to use this, apply expression towards the end of the template finalising ! Unless a different approach could be suggested.Overall – great piece of work!
Find out more:
Motion Graphics Design & After Effects Tutorials
On YT
On VH -
Filip Vandueren
July 11, 2020 at 7:18 pmI have tested it now – see benchmark test in attachment.
14215_pngcroptest.zipall comps were 300 frames long.
case 1: PNG_circle is a 500×500 PNG with a 300px circle in it.
-> test 1 = calculate the sourceRect every frame = 7 seconds
-> test 2 = calculate the sourceRect in a 1 frame helper comp = 5 seconds
-> test 3 = just render out the sequence as is without any expressions = 4 secondscase 2: PNG_dot is a 1900×1900 PNG with just a 8px circle in it. (stresstest!)
-> test 1 = calculate the sourceRect every frame = 81 seconds
-> test 2 = calculate the sourceRect in a 1 frame helper comp = 4 seconds
-> test 3 = just render out the sequence as is without any expressions = 4 seconds -
Malcolm Ricci
July 13, 2020 at 9:41 amThanks a lot for the expression work and for the project sample, Filip, you’ve saved me countless hours of research and trying to figure this out.
Also thanks once again Tomas for the input and valuable tips.
It’s going to be a long road ahead getting comfortable with this level of expressions, but we’ll get there ☺
Malcolm
-
Filip Vandueren
August 18, 2020 at 8:32 pmFollow-up…
I’ve just discovered that since After Effects 16.0
starting an expression with posterizeTime(0); will force it to be only executed once.
So no need for helper-comps and valueAtTime(0) -
Oscar Nyquist
February 11, 2022 at 2:08 pmThanks a lot for your amazing work on this! I’m also in need of a similar solution.
I need to store the data as a value in a slider. However, using your method, I’m having some issues. It all works fine as long as it’s stored as a text string, but trying to parse it into a value seems to break the expression and just gives me a faulty value.
I tried fiddling around with it a lot, even bypassing the JSON string and putting the expression directly on a slider. I finally figured out the issue seems to be with the posterizeTime expression. When I set it to 1 or something higher than 0, it gives me the correct value. However, then the expression also becomes way too heavy for my usage, so it’s not really an option for me. Any ideas here?
Cheers!
Reply to this Discussion! Login or Sign Up
