Skip to main content
Known Participant
June 22, 2023
Question

Is possible to write a script that can AUTO CROP image to best fit aspect ratio ?

  • June 22, 2023
  • 4 replies
  • 5802 views

I have images that with differnt dimentions, mix with protrait and lanscape, is there any script can detect the image size then auto crop to best fit aspect raio : 1:1, 2:3, 3:4, 4:5, 5:7, 2:1, 3:1 / 3:2, 4:3, 5:4, 7:5, 1:2, 1:)

 

I tried ask chatGPT to help (LOL), it gave me some messy and cofused code.

 

Then I did a lot searches, no resources can provide some hints to start to code it.

 

Any ideas ? Thanks

4 replies

c.pfaffenbichler
Community Expert
Community Expert
June 25, 2023

Does this provide meaningful results? 

// determine closest ratio from a limited set;
// 2023, use at your own risk;
if (app.documents.length > 0) {
    app.togglePalettes();
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    var myDocument = activeDocument;
    var theW = myDocument.width;
    var theH = myDocument.height;
    var theProportion = theW/theH;
    var theProportions = [[2,3], [5,7], [3,4], [4,5], [1,1], [5,4], [4,3], [7,5], [3,2], [2,1], [3,1]];
    var theResult = theProportions.sort(sortArrayByDifference)[0];
    var thisProp = theResult[0]/theResult[1];
    if (theProportion < thisProp) {
        var targetW = theW;
        var targetH = theW*theResult[1]/theResult[0];
    }
    else {
        var targetW = theH*theResult[0]/theResult[1];
        var targetH = theH;
    };
    alert ("at the aspect ratio "+theResult.join("/")+" the image would be\n"+targetW+" x "+targetH);
    app.preferences.rulerUnits = originalRulerUnits;
    app.togglePalettes();
};
////// sort by difference to a number //////
function sortArrayByDifference(a,b) {
    if (Math.abs((a[0]/a[1])-theProportion)<Math.abs((b[0]/b[1])-theProportion)) return -1;
    if (Math.abs((a[0]/a[1])-theProportion)>Math.abs((b[0]/b[1])-theProportion)) return 1;
    return 0;
    };
Known Participant
June 25, 2023

Thank you very much, it works

I added

app.activeDocument.crop.........

and it works, thanks again

 

Stephen Marsh
Community Expert
Community Expert
June 26, 2023
quote

Thank you very much, it works

I added

app.activeDocument.crop.........

and it works, thanks again

 


By @Calvin21914323wi10

 

Please share the final code, I for one would be interested.

 

EDIT:

https://theiviaxx.github.io/photoshop-docs/Photoshop/Document/crop.html

 

Stephen Marsh
Community Expert
Community Expert
June 23, 2023

There are different algorithms to determine aspect ratios, the following code uses 3 different ones:

 

/*
Photoshop Document Dimensions - MP Value - Aspect Ratio.jsx
v1.0, Stephen Marsh 13th February 2022
*/

#target photoshop

var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;

var w = app.activeDocument.width.value;
var h = app.activeDocument.height.value;
var r = gcd(w, h);
var mp = w * h / 1000000;
var pix = w * h;
var ppiRes = app.activeDocument.resolution;
var ppcmRes = ppiRes / 2.54;
var ratio = w / h;
var docName = app.activeDocument.name;
var wMetric = w / 72 * 2.54;
var hMetric = h / 72 * 2.54;
var wInches = w / 72;
var hInches = h / 72;
var doc = app.activeDocument;
var w = doc.width.value;
var h = doc.height.value;

alert(
    'Document Info' + '\n' +
    'Document Name: ' + docName + '\n' +
    'Dimensions: ' + w + ' x ' + h + ' pixels' + '\n' +
    'Dimensions: ' + Math.round(wMetric * 100) / 100 + ' x ' + Math.round(hMetric * 100) / 100 + ' cm / ' + Math.round(wInches * 1000) / 1000 + ' x ' + Math.round(hInches * 1000) / 1000 + ' inches' + '\n' +
    'Resolution: ' + Math.round(ppiRes * 10) / 10 + ' ppi / ' + Math.round(ppcmRes * 1000) / 1000 + ' ppcm' + '\n' +
    'Megapixel Value: ' + Math.round(mp * 10) / 10 + ' MP' + ' (' + pix + ' pixels)' + '\n' +
    'Aspect Ratio:' + '\n' + ratio.toFixed(2) + ':1' + ' / ' + ratio.toFixed(2) * 2 + ':2 / ' + ratio.toFixed(2) * 4 + ':4' + ' (Basic)' + '\n' +
    w / r + ':' + h / r + ' (GCD)' + '\n' +
    aspect_ratio(w / h, 50).toString().replace(',', ':') + ' (Farey)'
);

app.preferences.rulerUnits = savedRuler;


function gcd(a, b) {
    /* https://stackoverflow.com/questions/1186414/whats-the-algorithm-to-calculate-aspect-ratio-i-need-an-output-like-43-169 */
    return (b == 0) ? a : gcd(b, a % b);
}

function aspect_ratio(val, lim) {

    var lower = [0, 1];
    var upper = [1, 0];

    while (true) {
        var mediant = [lower[0] + upper[0], lower[1] + upper[1]];

        if (val * mediant[1] > mediant[0]) {
            if (lim < mediant[1]) {
                return upper;
            }
            lower = mediant;
        } else if (val * mediant[1] == mediant[0]) {
            if (lim >= mediant[1]) {
                return mediant;
            }
            if (lower[1] < upper[1]) {
                return lower;
            }
            return upper;
        } else {
            if (lim < mediant[1]) {
                return lower;
            }
            upper = mediant;
        }
    }
}

 

Adobe Bridge has a filter for aspect ratio, which you can use to open all files in a folder with the same ratio... But you would have to determine the threshold and fuzziness as to what matches what.

Known Participant
June 23, 2023

Thank you very much, will test in my images.

Stephen Marsh
Community Expert
Community Expert
June 23, 2023

For your "1_43.jpg" sample, Bridge lists the aspect ratio as 3:4, however you would class this as 4:3 as it is landscape.

 

My script reports the following for the same image:

 

Aspect Ratio:

1.32:1 / 2.64:2 / 5.28:4 (Basic)

2374:1795 (GCD)

41:31 (Farey)

 

So the Farey formula is closest to Bridge in this case with rounding, but the GCD formula is better from memory in other cases.

 

I don't know if there is a single "best" formula. Math isn't my strong point, I had to adapt various JS codes for Photoshop.

 

Zesty_wanderlust15A7
Known Participant
June 22, 2023

Have you studied, understood, and tried the File > Automate > Fit Image... script and is it not what you want...?

 

If it only works for some photos, you could indeed write a script that uses a different Fit Image... depending on sizes or ratios the script detects — or just do them in separate batches.

 

PS: Fit Image will use the Image Interpolation set in Preferences.

Zesty_wanderlust15A7
Known Participant
June 22, 2023

BTW, you can also use Conditional steps, so you don't necessarily need your own script.

 

c.pfaffenbichler
Community Expert
Community Expert
June 22, 2023

I don’t think I fully understand the process. 

Could you post screenshots for an example (what do you start with, what is the intended final result, …)? 

Known Participant
June 23, 2023

Thank you, I uploaded 4 files (mixed with protrait and lanscape)

 

File 1 : 2374*1795, best fit with 4:3 aspect ratio crop

File 2 : 5768*4620, best fit with 5:4 aspect ratio crop

File 3 : 1290*1722, best fit with 3:4 aspect ratio crop

File 4 : 1001*1928, best fit with 1:2 aspect ratio crop

 

I have over 50 such files with different dimensions in a single folder; I want a script that can auto-detect their sizes and determine to crop them with varying best-fit ratios of aspect, then save them to different folders named 43, 54, 34, 12 and so on........

The images could be in 1:1, 2:3, 3:4, 4:5, 5:7, 2:1, 3:1, 3:2, 4:3, 5:4, 7:5 ratios. Even if I manually crop them, I still need to find out the best-fit aspect ratio many times, so I want automatic this to work.

This script is beyond my ability; any ideas to make it?

 

c.pfaffenbichler
Community Expert
Community Expert
June 23, 2023

Why do you list 2:3 and 3:2 and 4:5 and 5:4 etc. separately? 

Does this mean that 2:1 and 3:1 are only applicable to landscape and MUST NOT be applied to portrait?