Forum Replies Created

Page 21 of 277
  • Did you actually save it as a .png ? Or is the PNG a screenshot of an mp4 export ? Because it could be a result of chroma-subsampling on that hard color transition.

  • Filip Vandueren

    January 19, 2023 at 9:21 am in reply to: Constant speed Slow down

    Hi Tudor,

    it’s important to understand this key-point:

    you cannot control everything at once to get a constant speed slow down.

    I mean, you cannot define AND an arbitrary overshoot Distance (the extra [20,20]), AND a set time (1 extra second) AND a given starting speed (the amount travelled in the linear function) and make that result in a linear deceleration.

    At least 1 thing has to be set/precomputed to make the other 2 values work.

    For example, if you want the overshoot to be +[20,20], the time that needs to take for a linear deceleration from the given linear function is 0.4 seconds:

    b = easeX(1, 1.4, [0,0], [20,20]);

    should work perfectly.

    If on the other hand, you want the overshoot to last the full extra second, the overshoot distance needs to be [50,50];

    b = easeX(1, 2, [0,0], [50,50]);

    If you want to overshoot [20,20] and make that last 1 second, then the de-acceleration can’t be linear , and would need to be:

    var c = 1-Math.pow(1-x,5);

    etc.

    How to calculate these values:

    take this starting Point:

    startVal = [100,100]; endVal = [200,200];
    linearStartTime = 0; linearEndTime = 1;
    dampingCoefficient = 2; // 2 = linear deceleration
    overshootTime = 1;
    overshootAmount = 0.5;
    function easeX(startDur, endDur, startVal, endVal) {
    var x = linear(time, startDur, endDur, 0, 1);
    var c = 1-Math.pow(1-x, dampingCoefficient);
    return linear(c, 0, 1, startVal, endVal);
    };
    a = linear(time, linearStartTime, linearEndTime, startVal, endVal);
    overshootVal = mul(sub(endVal, startVal), overshootAmount);
    b = easeX(linearEndTime, linearEndTime+overshootTime, [0,0], overshootVal);
    a+b;

    This will work for any startVal/endVal combination.
    But not when you change the length of the linearStartTime – linearEndTime.

    If you want the overshoot to still be 50% of what was travelled in the linear section, overshootTime would have to be calculated as:

    overshootTime = linearEndTime-linearStartTime;

    But 50% is rather a lot of overshoot, so how to calculate the values for 20% (as in your original example):

    dampingCoefficient = 2; // 2 = linear deceleration
    overshootAmount = .2; // 20%
    overshootTime = (overshootAmount*dampingCoefficient)*(linearEndTime-linearStartTime);

    What if you want the overshootTime to be fixed to 1 second, and calculate the needed overshootAmount (thought this would be less realistic):

    dampingCoefficient = 2; // 2 = linear deceleration
    overshootTime = 1;
    overshootAmount = overshootTime/(dampingCoefficient*(linearEndTime-linearStartTime));

  • You can use this animation preset of mine to get subsourcerect (source rect of individual characters, words or lines of a textlayer):

    https://we.tl/t-gI5DRRI0b9

    demo (enable sound)

    https://imgur.com/gallery/9oRKx7R

  • Here’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
  • Filip Vandueren

    January 12, 2023 at 9:56 am in reply to: Scaleable Exponential Scale?

    Here’s another method, that works more like the animation assistent:

    Just keyframe your scale (I’m assuming 2D scales here) and apply this expression:

    if (numKeys>2) {
    nk = nearestKey(time);
    prevKeyIndex = (1, nk.index - (nk.time>time ? 1 : 0))||1;
    nextKeyIndex = Math.min(numKeys, prevKeyIndex+1)||1;
    prevValue_X = key(prevKeyIndex).value[0]||0.001;
    prevValue_Y = key(prevKeyIndex).value[1]||0.001;
    nextValue_X = key(nextKeyIndex).value[0]||0.001;
    nextValue_Y = key(nextKeyIndex).value[1]||0.001;
    expGrowth_X = Math.log(nextValue_X/prevValue_X);
    expGrowth_Y = Math.log(nextValue_Y/prevValue_Y);
    [
    prevValue_X * (Math.E ** linear(
    value[0],
    key(prevKeyIndex).value[0],
    key(nextKeyIndex).value[0],
    key(prevKeyIndex).value[0]< key(nextKeyIndex).value[0] ? 0 : expGrowth_X,
    key(prevKeyIndex).value[0]< key(nextKeyIndex).value[0] ? expGrowth_X : 0))
    ,
    prevValue_Y * (Math.E ** linear(
    value[1],
    key(prevKeyIndex).value[1],
    key(nextKeyIndex).value[1],
    key(prevKeyIndex).value[1]< key(nextKeyIndex).value[1] ? 0 : expGrowth_Y,
    key(prevKeyIndex).value[1]< key(nextKeyIndex).value[1] ? expGrowth_Y : 0))
    ];
    } else {
    value;
    }

    This has some of the limitations as the animation assistent: doesn’t handle negative scale (O scale is caught by changing it to a very small value 0.001)

    But this version respects the easing/velocities of your keyframes, so you can do exponential scale, with easing.

    The code can probably be a bit shorter.

    (note, since it uses ** as a shorthand for Math.pow() it needs the modern Javascript engine to work)

  • Filip Vandueren

    January 12, 2023 at 9:27 am in reply to: Scaleable Exponential Scale?

    I do this all the time:

    Create a slider on your layer then use this expression for scale:

    value * 2 ** (effect(“Slider Control”)(“Slider”).value/100);

    You can change /100 to +10 or whatever, just what gives you the best control. Not dividinng it at all makes it hard to finetune the scaling by scrubbing the slider as the values get huge quickly)

    Now keyframe the slider for true exponential scaling.

  • Filip Vandueren

    January 11, 2023 at 7:39 am in reply to: Ae Speed Acceleration… Thru Plugin Effect?

    For example, in a 32-bit project, a shape with this expression fill-color would have a color and alpha whose value translates directly to the current time, since it’s a floating point number, not bound between 0-100% like 8 and 16bpc colors are:

    time*[1,1,1,1];

    Timewarp should be set to Frame Mix, and the precomp can be tiny (4px * 4px) so it’s as low a performance hit as possible to render and sample:

    thisLayer.sampleImage([2,2], radius = [1, 1], postEffect = true, t = time)[0];

  • Filip Vandueren

    January 11, 2023 at 7:30 am in reply to: Ae Speed Acceleration… Thru Plugin Effect?

    Timewarp also has a keyframeable speed paramater and is specifically designed to do timing.

    There’s no straightforward way way to extract the value though.

    One hacj/strategy to get the value could be this:

    In a 16 or 32 bit project, create a precomp that animates its color from black to white b(or superwhite in 32bpc)

    Use Timewarp with something like a wiggle() on speed to retime that fade in,

    Use sampleImage() to convert the grayscale back to a number and you have the resulting timing of the wiggle.

    I’m just brainstorming a hack, not saying this is a solid performing method for production 🙂

  • Filip Vandueren

    December 19, 2022 at 9:13 am in reply to: SOURCERECTATTIME FOR STRING

    Hi René,

    The coordinates are relative to the anchorPoint of the text-layer.

    If the text is right- or center-aligned, it makes sense that some of the coordinates will be negative (to the left of the anchorPoint).

    The easiest way to implement it in a shape, is to parent the shape to your text-layer, and make sure all positions/anchorpoints of the shape layer and its groups are at [0,0].

    If you now use the coordinates in a createPath() the vertices should line up.

    if you don’t want to parent, you need to use (pseudocode:)

    shapeLayer.fromComp(textLayer.toComp( vertex ))

Page 21 of 277

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