• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

Scripts: How can I used scripts to get dimensions of an image?

Community Beginner ,
Feb 01, 2024 Feb 01, 2024

Copy link to clipboard

Copied

I have a script that should take a template image -500x500, and any image I use to replace it should fit within the 500x500. 

So if I use a source image that is 900x900, it should scaled it down to fit the template image that is 500x500. 


How can I determine the templates image size (dimensions), and then use that to determine the the scaling that needs to be done?

TOPICS
Scripting

Views

214

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 01, 2024 Feb 01, 2024

Copy link to clipboard

Copied

What should happen if the replacemenrt image is not the same aspect ratio as the template image? Scrunch (non-uniform scaling) or crop (fit to height or width)? Also, does the script have to worry about non-square pixels?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 02, 2024 Feb 02, 2024

Copy link to clipboard

Copied

Let's just assume that the aspect ratio will always match. Always a square. Here is my old implementation of image swapping without any scaling adjustments - this assumes I have the exact image dimensions for the replacement:

        // Check image layer replacement
        for (var h = 0; h < headers.length; h++) {
            var headerName = headers[h];

            if (layer.source && originalLayerName === headerName) {
                var relativeImagePath = row[headerName];

                if (!relativeImagePath) {
                    layer.enabled = false;
                    continue;
                }

                var absoluteImagePath = getAbsolutePath(relativeImagePath);
                replaceImageSource(layer, absoluteImagePath);

                // Reset the layer's name to its original name after the source is replaced
                layer.name = originalLayerName;


And here is my attempt measuring the layer its replacing, and applying scaling on the replacement image - also making sure the replacement is in the same spot (replacing it, so all keyframes if any are inherited):

for (var k = 1; k <= comp.numLayers; k++) {
    var layer = comp.layer(k);
    var originalLayerName = originalLayerNames[k - 1];

    // Check image layer replacement
    for (var h = 0; h < headers.length; h++) {
        var headerName = headers[h];

        if (layer instanceof AVLayer && originalLayerName === headerName) {
            var relativeImagePath = row[headerName];

            if (!relativeImagePath) {
                layer.enabled = false;
                continue;
            }

            var absoluteImagePath = getAbsolutePath(relativeImagePath);

            // Get the original layer's bounds including scale
            var originalBounds = layer.sourceRectAtTime(0, false);
            var originalWidth = originalBounds.width * layer.scale.value[0] / 100;
            var originalHeight = originalBounds.height * layer.scale.value[1] / 100;

            // Replace the image source
            replaceImageSource(layer, absoluteImagePath);

            // Calculate the new image's bounds
            var newBounds = layer.sourceRectAtTime(0, false);
            var newWidth = newBounds.width;
            var newHeight = newBounds.height;

            // Calculate the scale factor to match original layer size
            var scaleX = originalWidth / newWidth * 100;
            var scaleY = originalHeight / newHeight * 100;

            // Apply the scale factor
            layer.scale.setValue([scaleX, scaleY]);

            layer.name = originalLayerName;

This worked. Now I have another condition where in some instances, ill be replacing a video instead of an image, and the same thing should happen. But my video has some keyframes, so I get an error when using this above method (the keyframe is at the end of the comp, basically take the static placed video and zooming in). The error I got was Can not call setValue() on a property with keyframes. Use SetValueAtTime() or SetValueAtKey() instead.

I tried and tried to get it to work with the keyframes, essentially I want it to replace the video and keep it's keyframe the same so it still is static and zooms at the end. My attempts here resulted in the video being replaced, but doing some weird zooming:

 // Check video layer replacement
    for (var h = 0; h < headers.length; h++) {
        var headerName = headers[h];

        if (layer instanceof AVLayer && originalLayerName === headerName) {
            var relativeVideoPath = row[headerName];

            if (!relativeVideoPath) {
                layer.enabled = false;
                continue;
            }

            var absoluteVideoPath = getAbsolutePath(relativeVideoPath);

            // Replace the video source
            replaceVideoSource(layer, absoluteVideoPath); // Assuming this function exists

            // If the layer has keyframes, we adjust only the first keyframe scale
            if (layer.scale.numKeys > 0) {
                var firstKeyTime = layer.scale.keyTime(1);
                var originalFirstKeyScale = layer.scale.keyValue(1);

                // Calculate the scale factor based on the new video dimensions
                var newWidth = layer.source.width;
                var newHeight = layer.source.height;
                var originalWidth = originalFirstKeyScale[0] / 100 * comp.width; // Assuming the original scale is relative to comp size
                var originalHeight = originalFirstKeyScale[1] / 100 * comp.height;

                var scaleX = originalWidth / newWidth * 100;
                var scaleY = originalHeight / newHeight * 100;

                layer.scale.setValueAtKey(1, [scaleX, scaleY]);
            }

            layer.name = originalLayerName;


So lastly, i decided since I can't get the video swap to work, I'll just have it skip the scaling and just replace as normal, but only apply scaling to images - which worked well before - but somehow - adding the condition to check for videos/stills changes the images scaling. So while it worked and was perfectly positioned and scaled in the prior working code above, adding the condition makes it now a little bigger than desired and not taking the dimensions of the image it replaced:

   // Check image layer replacement
    for (var h = 0; h < headers.length; h++) {
        var headerName = headers[h];

        if (layer instanceof AVLayer && originalLayerName === headerName) {
            var relativePath = row[headerName];

            if (!relativePath) {
                layer.enabled = false;
                continue;
            }

            var absolutePath = getAbsolutePath(relativePath);

            // Replace the image source
            replaceImageSource(layer, absolutePath);

            // Check if the layer is a still image
            var isStillImage = layer.source.mainSource.isStill;

            if (isStillImage) {
                // Get the original layer's bounds including scale
                var originalBounds = layer.sourceRectAtTime(0, false);
                var originalWidth = originalBounds.width * layer.scale.value[0] / 100;
                var originalHeight = originalBounds.height * layer.scale.value[1] / 100;

                // Calculate the new image's bounds
                var newBounds = layer.sourceRectAtTime(0, false);
                var newWidth = newBounds.width;
                var newHeight = newBounds.height;

                // Calculate the scale factor to match original layer size
                var scaleX = originalWidth / newWidth * 100;
                var scaleY = originalHeight / newHeight * 100;

                // Apply the scale factor
                layer.scale.setValue([scaleX, scaleY]);
            }

            layer.name = originalLayerName;




Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 02, 2024 Feb 02, 2024

Copy link to clipboard

Copied

Instead of trying to set the scale value directly, you could apply a scale expression that adjusts the scale based on the ratio of the original size to the new size, like this:

var scaleX = originalWidth / newWidth;
var scaleY = originalHeight / newHeight;
layer.scale.expression  = "[value[0]*" + scaleX + ", value[1]*" + scaleY + "]";

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 10, 2024 Feb 10, 2024

Copy link to clipboard

Copied

LATEST

Thanks Dan, this worked. Can't believe I didn't think to control the dimensions on the expression level vs scripting. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines