Forums › Adobe After Effects Expressions › how can i center the anchor point based on opacity of a comp’s contents?
-
how can i center the anchor point based on opacity of a comp’s contents?
-
Seth Olson
December 21, 2022 at 11:16 pmi have a comp with transparency. i want to center the anchor point of the comp to the area of opacity. I tried this on the comp:
// [CENTER, CENTER]
l = thisLayer.sourceRectAtTime();
[l.left + l.width/2, l.top + l.height/2];but it seems to measure the entire comp, not the opaque areas. Suggestions?
-
Dan Ebberts
December 21, 2022 at 11:26 pmThe only thing I can think of is the old brute-force sampleImage() method:
h = height/2;
w = width/2;
for (i = 0; i < width; i++){
if (sampleImage([i,h],[.5,h])[3]>0) break;
}
left = i;
for (i = width-1; i >= 0; i--){
if (sampleImage([i,h],[.5,h])[3]>0) break;
}
right = i;
for (i = 0; i < height; i++){
if (sampleImage([w,i],[w,.5])[3]>0) break;
}
top = i;
for (i = height-1; i >= 0; i--){
if (sampleImage([w,i],[w,.5])[3]>0) break;
}
bottom = i;
[(left+right)/2,(top+bottom)/2] -
Dan Ebberts
December 22, 2022 at 7:06 pmI think this is actually a little (half a pixel) more precise:
h = height/2;
w = width/2;
for (i = 0.5; i < width; i++){
if (sampleImage([i,h],[.5,h])[3]>0) break;
}
left = i;
for (i = width-0.5; i > 0; i--){
if (sampleImage([i,h],[.5,h])[3]>0) break;
}
right = i;
for (i = 0.5; i < height; i++){
if (sampleImage([w,i],[w,.5])[3]>0) break;
}
top = i;
for (i = height-0.5; i > 0; i--){
if (sampleImage([w,i],[w,.5])[3]>0) break;
}
bottom = i;
[(left+right)/2,(top+bottom)/2] -
Seth Olson
December 22, 2022 at 8:06 pmOk, this works very well, but also very slowly. It requires several seconds to process each frame.
Is there a way to get the property using sourceRectAtTime() on the first layer inside the comp?
something like: sc=comp(“1”).layer(0).sourceRectAtTime();
but then I get an error that “index 0 is out of range”
maybe something made up like: thisLayer.firstLayer.sourceRectAtTime();
Thank you for your help!
-
Dan Ebberts
December 22, 2022 at 9:53 pmsourceRectAtTime() won’t detect the zero-alpha areas of precomp layers.
You could always convert the anchor point expression to keyframes. That might help.
-
Filip Vandueren
January 12, 2023 at 10:20 amHere’s a version that uses binary search so is exponentially faster:
Note that it works best in 16 or 32 bpc for images that have a very small amount of opaque pixels ( < 0,4%)
// posterizeTime(0); // uncomment for still images
includeEffects = false;
l=thisLayer;
w=l.source.width;
h=l.source.height;
threshold = 0;
width_bits = Math.ceil(Math.log(w)/Math.log(2));
height_bits = Math.ceil(Math.log(h)/Math.log(2));
left = 0; right = 0;
for (b=width_bits-1; b>=0; b--) {
slice_width = 2**b;
if (l.sampleImage([left + slice_width/2, h/2], [slice_width/2, h/2],includeEffects)[3]<=threshold) {
left+=slice_width;
}
if (l.sampleImage([w - (right + slice_width/2), h/2], [slice_width/2, h/2],includeEffects)[3]<=threshold) {
right+=slice_width;
}
}
right= w-right;
top = 0; bottom = 0;
for (b=height_bits-1; b>=0; b--) {
slice_height = 2**b;
if (l.sampleImage([w/2, top + slice_height/2], [w/2, slice_height/2],includeEffects)[3]<=threshold) {
top+=slice_height;
}
if (l.sampleImage([w/2, h - (bottom + slice_height/2)], [w/2, slice_height/2],includeEffects)[3]<=threshold) {
bottom+=slice_height;
}
}
bottom = h-bottom;
[left+right, top+bottom]/2
Log in to reply.