Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions scale up non transparent portion of layer to composition

  • scale up non transparent portion of layer to composition

    Posted by Adam Greenberg on April 12, 2023 at 9:20 pm

    Hi all, I had 2 precomps working well with 2 seperate codes, and with no surprise I find myself needing a combination of the 2.

    Basically, I have a composition that will have a graphic in it ( which will be replaced by the user each time when the client sends one )

    I have an expression that auto scales this layer to the composition bounds.

    In a different composition, Filip has come up with a great expression that looks for a top edge of a layer.

    I now realize that some 3rd party graphics we are receiving have too many transparent pixels around the graphic. So is there a way to re-write this expression so that the graphic will scale up according to non transparent pixels ? I would think the sampleimage part of the code could be worked into the original expression to have the graphic fill the comp even if there are 100 pixels of transparency around the graphic;

    the scale to comp code;

    x=100*thisComp.width/thisLayer.width;

    y=100*thisComp.height/thisLayer.height;

    if(x>=y)

    [y,y];

    else [x,x]

    and the find top edge code;

    posterizeTime(0);

    s=thisComp.layer(“logo”).transform.scale[0]

    const l = thisComp.layer(“logo”);

    const w = l.width;

    const h = l.height;

    const heightLog2 = Math.ceil(Math.log(h)/Math.log(2));

    const threshold = 1; // on average 1 pixel in a row is opaque to count as the topEdge;

    var topEdge = 0;

    for(i=heightLog2; i>-1; i–) {

    let partition = 2 ** i;

    let ss = l.sampleImage([w / 2, topEdge+partition/2], [w / 2, partition/2], false, time);

    if (ss[3]<=threshold/(w*partition)) topEdge+=partition;

    }

    [960, l.toComp([w/2, topEdge])[1] +50 ];

    Thanks for any help.

    Filip Vandueren replied 5 months, 1 week ago 2 Members · 5 Replies
  • 5 Replies
  • Filip Vandueren

    April 13, 2023 at 8:38 am

    Hey Adam,

    This gives you everything you need:

    posterizeTime(0);
    const l = thisComp.layer("Logo");
    const w = l.width;
    const h = l.height;
    const heightLog2 = Math.ceil(Math.log(h)/Math.log(2));
    const widthLog2 = Math.ceil(Math.log(w)/Math.log(2));
    const threshold = 1; // on average 1 pixel in a row is opaque to count as the topEdge;
    var topEdge = 0;
    var bottomEdge = h;
    for(i=heightLog2; i>-1; i--) {
    let partition = 2 ** i;
    let s = l.sampleImage([w / 2, topEdge+partition/2], [w / 2, partition/2], false, time);
    if (s[3]<=threshold/(w*partition)) topEdge+=partition;
    s = l.sampleImage([w / 2, bottomEdge-partition/2], [w / 2, partition/2], false, time);
    if (s[3]<=threshold/(w*partition)) bottomEdge-=partition;
    }
    var leftEdge = 0;
    var rightEdge = w;
    for(i=widthLog2; i>-1; i--) {
    let partition = 2 ** i;
    let s = l.sampleImage([leftEdge+partition/2, h / 2], [partition/2, h / 2], false, time);
    if (s[3]<=threshold/(h*partition)) leftEdge+=partition;
    s = l.sampleImage([rightEdge-partition/2, h / 2], [partition/2, h / 2, ], false, time);
    if (s[3]<=threshold/(h*partition)) rightEdge-=partition;
    }
    alphaRect= {
    left: leftEdge,
    top: topEdge,
    right: rightEdge,
    bottom: bottomEdge,
    width: rightEdge-leftEdge,
    height: bottomEdge - topEdge,
    center: mul([leftEdge+rightEdge, topEdge+bottomEdge],0.5)
    };

    With this setup code you can use the properties of alphaRect on scale and anchorPoint to center and scale up like this:

    anchorPoint:

    alphaRect.center;

    scale:

    mul(
    [100,100],
    Math.min(thisComp.width/alphaRect.width, thisComp.height/alphaRect.height)
    );

    Now, because both scale and anchorPoint need to know the value of alphaRect, you will have to copy the whole first code in both, and only add that last bit for each.

    and maybe position needs to be explicitly centered ?

    [thisComp.width/2, thisComp.height/2];

  • Adam Greenberg

    April 13, 2023 at 2:02 pm

    Thanks so much Filip, I am testing it now, so first I obviously need to replace the 2nd line with

    l = thislayer;

    if i want the layer to scale up to the comp.

    so with my first 2 tests work perfectly ( although the scale is showing a negative value – but it is displaying correctly, so I dont understand how that can be )


    but on a graphic that has 50 pixels of transparency all around it, it is not filling the screen and is inverted due to the negative value.


    here is a link if you would like to see


    https://1drv.ms/u/s!AsjWkDwGUfVsgapN1mUcEUAstBI-_w

  • Filip Vandueren

    April 14, 2023 at 7:06 pm

    Hey Adam,

    There’s a bug in After Effects that when using posterizeTime(0) it shows you a wrong value in the timeline, but it’s not the actual value being used.

    if you change to posterizeTime(0.1), or omit the line, you’ll see the same visual result, but the actual number that’s calculated. So even though it says the scale is reported as negative, it is behind the scenes correct. (if you pick whip a different property to it, you’ll see the correct value for example)

    The layer that doesn’t work is continuously rasterized, which seems to confuse the coordinate system sampleImage uses, not sure how to fix that…

    perhaps by using 1 invisible non continuosly rasterized version as a parent of the rasterized one is a quick hack.

  • Adam Greenberg

    April 17, 2023 at 2:55 pm

    thanks so much for the clarification

  • Filip Vandueren

    April 18, 2023 at 6:58 am

    BTW,

    const heightLog2 = Math.ceil(Math.log(h)/Math.log(2));
    const widthLog2 = Math.ceil(Math.log(w)/Math.log(2));

    These should both be Math.floor in hindsight.

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy