Copy link to clipboard
Copied
Thanks to @c.pfaffenbichler teach me how to detact best fit ration for various images, however, photoshop scripts looks do no support crop with ratio
app.activeDocument.crop
from Abobe official guide - crop (bounds, [, angle], [, width], [, height])
means it only support crop in pixels dimention (not accurate), any methods to crop in ratio same as we use crop tools ?
1 Correct answer
@Calvin21914323wi10 – Try this:
/*
Auto Crop to Nearest Aspect Ratio.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-using-script-crop-image-by-aspect-ratio/td-p/13938028
From:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/is-possible-to-write-a-script-that-can-auto-crop-image-to-best-fit-aspect-ratio/td-p/13883327
By Calvin21914323wi10
Based on code from c.pfaffenbichler
#2 - Amendments by Stephen Marsh
*/
#target photoshop
if (app.documents.lengt
...
Explore related tutorials & articles
Copy link to clipboard
Copied
The previous topic mentioned above can be found here:
Copy link to clipboard
Copied
means it only support crop in pixels dimention (not accurate), any methods to crop in ratio same as we use crop tools ?
By Calvin21914323wi10
Images are composed of pixels, Photoshop works in pixels, so other units are therefore derived from pixels. Why do you say that cropping by pixel dimension isn't accurate if the end result is the correct aspect ratio?
Take a 1100 x 1000 pixel sized image as an example, using the crop tool to crop to 1:1 square ratio for a centre crop. The ScriptListener recorded AM code looks like this:
var idcrop = stringIDToTypeID( "crop" );
var desc298 = new ActionDescriptor();
var idto = stringIDToTypeID( "to" );
var desc299 = new ActionDescriptor();
var idtop = stringIDToTypeID( "top" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc299.putUnitDouble( idtop, idpixelsUnit, 0.000000 );
var idleft = stringIDToTypeID( "left" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc299.putUnitDouble( idleft, idpixelsUnit, 50.000000 );
var idbottom = stringIDToTypeID( "bottom" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc299.putUnitDouble( idbottom, idpixelsUnit, 1000.000000 );
var idright = stringIDToTypeID( "right" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc299.putUnitDouble( idright, idpixelsUnit, 1050.000000 );
var idrectangle = stringIDToTypeID( "rectangle" );
desc298.putObject( idto, idrectangle, desc299 );
var idangle = stringIDToTypeID( "angle" );
var idangleUnit = stringIDToTypeID( "angleUnit" );
desc298.putUnitDouble( idangle, idangleUnit, 0.000000 );
var iddelete = stringIDToTypeID( "delete" );
desc298.putBoolean( iddelete, true );
var idcropAspectRatioModeKey = stringIDToTypeID( "cropAspectRatioModeKey" );
var idcropAspectRatioModeClass = stringIDToTypeID( "cropAspectRatioModeClass" );
var idpureAspectRatio = stringIDToTypeID( "pureAspectRatio" );
desc298.putEnumerated( idcropAspectRatioModeKey, idcropAspectRatioModeClass, idpureAspectRatio );
var idconstrainProportions = stringIDToTypeID( "constrainProportions" );
desc298.putBoolean( idconstrainProportions, true );
executeAction( idcrop, desc298, DialogModes.NO );
Here it is cleaned into a function, which might be easier to read:
crop(0, 50, 1000, 1050, 0, true, true);
function crop(top, left, bottom, right, angle, delete2, constrainProportions) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putUnitDouble( s2t( "top" ), s2t( "pixelsUnit" ), top );
descriptor2.putUnitDouble( s2t( "left" ), s2t( "pixelsUnit" ), left );
descriptor2.putUnitDouble( s2t( "bottom" ), s2t( "pixelsUnit" ), bottom );
descriptor2.putUnitDouble( s2t( "right" ), s2t( "pixelsUnit" ), right );
descriptor.putObject( s2t( "to" ), s2t( "rectangle" ), descriptor2 );
descriptor.putUnitDouble( s2t( "angle" ), s2t( "angleUnit" ), angle );
descriptor.putBoolean( s2t( "delete" ), delete2 );
descriptor.putEnumerated( s2t( "cropAspectRatioModeKey" ), s2t( "cropAspectRatioModeClass" ), s2t( "pureAspectRatio" ));
descriptor.putBoolean( s2t( "constrainProportions" ), constrainProportions );
executeAction( s2t( "crop" ), descriptor, DialogModes.NO );
}
So even the crop tool works in pixels when you select a ratio.
Anther way to automate cropping is to crop from a selection using the Image > Crop command:
// A selection must be active
executeAction(stringIDToTypeID("crop"), undefined, DialogModes.NO);
// You may wish to deselect
So you can certainly create a temporary layer object at a specific ratio and position, load a selection, crop to the selection and remove the temporary object.
Finally, you can use canvas size to crop.
Perhaps the following links will help:
Copy link to clipboard
Copied
I am still a bit lost, here is an example, attached 3 file original, crop_tool, script_crop
Original is 800*1214, best fit ration is 2:3 which should be 800*1200
Crop Tool crop it 800*1200 - exact value
script_crop crop it to 800*1193 - ? ?
your calcuation is correct but my added code have problem - I think the mistake is in following
var bounds = [0,0,targetW,targetH]
app.activeDocument.crop(bounds);
I don't know how to set bounds - I think
How to crop in the centre of image ? any hints ?
Copy link to clipboard
Copied
@Calvin21914323wi10 – Try this:
/*
Auto Crop to Nearest Aspect Ratio.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-using-script-crop-image-by-aspect-ratio/td-p/13938028
From:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/is-possible-to-write-a-script-that-can-auto-crop-image-to-best-fit-aspect-ratio/td-p/13883327
By Calvin21914323wi10
Based on code from c.pfaffenbichler
#2 - Amendments by Stephen Marsh
*/
#target photoshop
if (app.documents.length > 0) {
app.togglePalettes();
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var myDocument = activeDocument;
var theW = myDocument.width.value;
var theH = myDocument.height.value;
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;
}
// Calculate centre crop
var diffW = theW - targetW;
var offsetW = diffW / 2;
var diffH = theH - targetH;
var offsetH = diffH / 2;
var bounds = [offsetW, offsetH, Math.round(targetW) + offsetW, Math.round(targetH) + offsetH];
//var bounds = [0, 0, targetW, targetH];
// Disable or remove the alert for batch processing
alert("At the aspect ratio " + theResult.join(":") + " the image would be" + "\n" + targetW + " x " + targetH + " px");
/* https://theiviaxx.github.io/photoshop-docs/Photoshop/Document/crop.html */
// Crop to bounds
app.activeDocument.crop(bounds,null,null,null);
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;
}
P.S. I have revised the original code a little, make sure that you are using the updated version #2.
Copy link to clipboard
Copied
Thank you so much, will test and post result.
Copy link to clipboard
Copied
Bingo, works accurately, appreciated for your help
Copy link to clipboard
Copied

