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

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

Participant ,
Jun 21, 2023 Jun 21, 2023

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

TOPICS
Actions and scripting , Windows
3.6K
Translate
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
Adobe
Community Expert ,
Jun 22, 2023 Jun 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, …)? 

Translate
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
Participant ,
Jun 22, 2023 Jun 22, 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?

 

Translate
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 ,
Jun 23, 2023 Jun 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? 

Translate
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
Participant ,
Jun 23, 2023 Jun 23, 2023

Yes, strictly follow the original art image.

Translate
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 ,
Jun 23, 2023 Jun 23, 2023

Once upon a time I was creating program in Python to do similar thing, to determine best available solution. I do not know how to using Javascript. Maybe you can find something already writen in JavaScript for similar purpose and to use it for manual work, at least. 

Translate
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
People's Champ ,
Jun 23, 2023 Jun 23, 2023
quote

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

 

By @Calvin21914323wi10

 

Didn't check everything, but it works on your data.

 

alert("2374*1795 " + get_optimal_crop(2374, 1795));
alert("5768*4620 " + get_optimal_crop(5768, 4620));
alert("1290*1722 " + get_optimal_crop(1290, 1722));
alert("1001*1928 " + get_optimal_crop(1001, 1928));

function get_optimal_crop(w,h)
    {
    try {
        var crops = [[1,1], [1,2], [1,3], [2,3], [3,4], [4,5], [5,7]];

        var a0 = 0;
        var i0 = 0;

        for (var i = 0;  i < crops.length; i++)
            {
            var a = get_area();
        
            if (a0 < a) { a0 = a; i0 = i; }

            function get_area()
                {
                try {
                    var w1, h1;
    
                    if (w > h && crops[i][0] < crops[i][1])
                        {
                        var tmp = crops[i][0];
                        crops[i][0] = crops[i][1];
                        crops[i][1] = tmp;
                        }
    
                    var w0 = crops[i][0];                    
                    var h0 = crops[i][1];                    
            
                    if (w/h < w0/h0)
                        {
                        w1 = w;
                        h1 = Math.round(w*h0/w0);
                        }
                    else
                        {            
                        h1 = h;
                        w1 = Math.round(h*w0/h0);
                        }    
    
                    return w1*h1;
                    } 
                catch(e) { throw(e); }
                }
            }

        return crops[i0];
        }
    catch(e) { throw(e); }
    }

 

 

 

 
Translate
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
Participant ,
Jun 24, 2023 Jun 24, 2023

Tested, I don't know why just no respose at all

Translate
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 ,
Jun 24, 2023 Jun 24, 2023
quote

Tested, I don't know why just no respose at all


By @Calvin21914323wi10

Wikipedia states 

»Repose is a word meaning "rest" or "calmness".«

so there might be a typo. 

Translate
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
Participant ,
Jun 24, 2023 Jun 24, 2023

Response, I mean. I ran it but nothing happened at all

Translate
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
Advocate ,
Jun 22, 2023 Jun 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.

Translate
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
Advocate ,
Jun 22, 2023 Jun 22, 2023

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

 

conditional atn.jpg

Translate
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 ,
Jun 23, 2023 Jun 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.

Translate
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
Participant ,
Jun 23, 2023 Jun 23, 2023

Thank you very much, will test in my images.

Translate
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 ,
Jun 23, 2023 Jun 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.

 

Translate
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
Participant ,
Jun 24, 2023 Jun 24, 2023

Tested, it can detect and show information but not crop the image

Translate
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 ,
Jun 24, 2023 Jun 24, 2023
quote

Tested, it can detect and show information but not crop the image


By @Calvin21914323wi10

One can crop both via DOM- and AM-code so what is giving you problems? 

 

Translate
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
Participant ,
Jun 25, 2023 Jun 25, 2023

Yes, I tried run in action, no crop, then I added my own crop function, still not work, maybe I am too stupid to code

Translate
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 ,
Jun 24, 2023 Jun 24, 2023
quote

Tested, it can detect and show information but not crop the image


By @Calvin21914323wi10

 

That is correct, the solution isn't handed to you on a silver platter!

 

Before one can even think about cropping, a suitable aspect ratio detection method has to be found, and then you have to determine some sort of pass/fail threshold tolerance etc.

Translate
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
Participant ,
Jun 25, 2023 Jun 25, 2023

Thank you, but even the best one - Farey, still not give out a exact ratio e.g.File 4 - best fit is 1:2, but it gave 13:25 very accurate but not a POPULAR RATIO (SELLERABLE PRINT SIZE RATIO), I hope you understand what I want to say.

 

Now I am trying use excel find my algorithm, but found many weird ratio in my collection, scratching my head and try to do more market research

Translate
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 ,
Jun 25, 2023 Jun 25, 2023

Indeed, these are the challenges.

 

Have you looked at the Adobe Bridge aspect ratio filter?

Translate
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 ,
Jun 25, 2023 Jun 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;
    };
Translate
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
Participant ,
Jun 25, 2023 Jun 25, 2023

Thank you very much, it works

I added

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

and it works, thanks again

 

Translate
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 ,
Jun 26, 2023 Jun 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

 

Translate
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
Participant ,
Jun 26, 2023 Jun 26, 2023

Thanks to @c.pfaffenbichler , I added 2 lines only

 

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 = [[1,3],[1,2],[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;
    };
	var bounds = [0,0,targetW, targetH]
    alert ("at the aspect ratio "+theResult.join("/")+" the image would be\n"+targetW+" x "+targetH);
	app.activeDocument.crop(bounds);
    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;
    };

 

Translate
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