Copy link to clipboard
Copied
I'm using Windows 10 with the latest build of Photoshop 2024.
I primarily take photos of birds. Instead of playing around with the crop tool, can I have a form allow me to define the percentage of the top, bottom, left, and right to crop. I’d then like to be able to click on a button that will define the subject and either perform the crop or outline it for me to review before proceeding.
There are going to be times when the bird is so surrounded by vegetation that Photoshop will not be able to correctly define the subject, so in those cases, I would need to be able to use a tool to draw around the bird to define it.
Also, with a fixed percentage definition, can I then batch files with the same crop?
You can try the following script. It's interactive, once you know what the average/common % margin values are, it is easy to update these values and turn off the interactive step so that this can be batched.
EDIT: I have updated the original interactive guide layout code to now work in % without manually setting the units.
The script will then crop to the guides and remove the guides. The cropped pixels can be retained or permanently deleted by changing false to true i
...Copy link to clipboard
Copied
Instead of playing around with the crop tool, can I have a form allow me to define the percentage of the top, bottom, left, and right to crop. I’d then like to be able to click on a button that will define the subject and either perform the crop or outline it for me to review before proceeding.
There are going to be times when the bird is so surrounded by vegetation that Photoshop will not be able to correctly define the subject, so in those cases, I would need to be able to use a tool to draw around the bird to define it.
Also, with a fixed percentage definition, can I then batch files with the same crop?
By @Mark37430984r9lw
The crop tool is generally for visual cropping with options such as ratio, rule of thirds grid etc.
What you describe isn't a standard feature. An action, or better yet – a script could be used to do some of what you are asking for without a preview.
Why would using arbitrary % values for left/top/right/bottom be any better than the standard crop tool, or a Select All followed by Select > Transform Selection and then Image > Crop?
Can the Select > Select Subject command successfully and consistently identify the bird as the area of interest?
You mention both interactive and batch cropping. Do you want the batch to be interactive or fully automated?
It would help if you could provide before/after example images to illustrate.
Much of your post sounds like an idea/feature request for future development, however, that would require a better description of the process and or mock-up illustrations of the process.
Copy link to clipboard
Copied
I just realized I've been using the rectangular marquee tool for crops, not the crop tool. Not certain whether this makes a difference with the discussion.
I just tried selecting the subject with an original bird photo where the bird was small in the frame and Photoshop had no idea what the subject was. I then selected the subject from the same pic that I had cropped, and it selected only the subject.
Maybe if I elaborate my intentions, somebody can lead me to some PS functionality that already exists. I learned from an instructional video that if a bird is facing a certain direction, a photo looks much better with a tight crop on the opposite side with more space in the direction the bird is facing/looking. My personal preference is to crop a little more tightly on the top than the bottom. I do a reasonable job of hand cropping to these specifications, but this takes too long. I’d like to come up with some “sweet spot” formulas on how much to crop each side. I’m using the plural here, as I realize that the ideal percentages are going to vary depending on how much the bird is in frame, and how centered it originally was. So, if I could use some kind of form or even a script to try some formulas and look at the results, this would save me a lot of time and effort. I don’t want to temporarily isolate the bird and the background, and then put the subject back in a different part of the background as part of the process. I submit photos for scientific research, and this would artificially change the natural environment that I’m not supposed to edit out of photos.
Regarding batch processing, I’d like it automated. I usually have a lot of similar burst shots, but the subject may have different poses, and the lighting may be better for some. It would save a ton of time if I could apply a crop formula to the entire batch at once. BUT, in instances where PS cannot find the subject, I realize this would not be feasible.
I’m very new to all of this. I’ve only been using full photoshop for three weeks now. I find it unlikely that PS does not have any built-in tools to accomplish what I want. Maybe some third-party plugin is what I need. I’m certain there are industry professionals, or much more experienced post-processors than I who use mathematical cropping formulas within Photoshop all of the time.
Copy link to clipboard
Copied
You can try the following script. It's interactive, once you know what the average/common % margin values are, it is easy to update these values and turn off the interactive step so that this can be batched.
EDIT: I have updated the original interactive guide layout code to now work in % without manually setting the units.
The script will then crop to the guides and remove the guides. The cropped pixels can be retained or permanently deleted by changing false to true in the crop function call.
/*
Canvas Margin Percentage Crop.jsx
v1.2 - 12th June 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/i-want-to-make-a-form-to-define-crops/td-p/14675929
*/
#target photoshop
// Check if a document is open
if (app.documents.length > 0) {
// Set the document variable
var doc = app.activeDocument;
// Get and set the ruler units
var origRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PERCENT;
// Conditionally clear existing guides
if (app.activeDocument.guides.length > 0)
app.runMenuItem(stringIDToTypeID('clearGuides'));
// Change ALL to NO to disable interactivity when batching
var interactive = DialogModes.ALL;
// Add 4 margin guides based on % of canvas size
// Enter your desired values - top, left, bottom, right
newGuideLayout(10, 25, 10, 25);
// Set the rulers to pixels
app.preferences.rulerUnits = Units.PIXELS;
// Get the existing guides
var guides = getGuides(doc);
if (guides.horizontal.length >= 2 && guides.vertical.length >= 2) {
// Sort the guides to find the outermost guides
guides.horizontal.sort(function(a, b) { return a - b; });
guides.vertical.sort(function(a, b) { return a - b; });
// Define the selection region based on the outermost guides
var selectionRegion = [
[guides.vertical[0], guides.horizontal[0]], // Top-left
[guides.vertical[guides.vertical.length - 1], guides.horizontal[0]], // Top-right
[guides.vertical[guides.vertical.length - 1], guides.horizontal[guides.horizontal.length - 1]], // Bottom-right
[guides.vertical[0], guides.horizontal[guides.horizontal.length - 1]] // Bottom-left
];
// Make the selection
doc.selection.select(selectionRegion);
// Crop to the selection: delete cropped pixels = true
cropToSelection(doc.selection.bounds[1], doc.selection.bounds[0], doc.selection.bounds[3], doc.selection.bounds[2], false);
// Conditionally clear existing guides
if (app.activeDocument.guides.length > 0)
app.runMenuItem(stringIDToTypeID('clearGuides'));
// Reset the original ruler units
app.preferences.rulerUnits = origRulerUnits;
} else {
alert("Please make sure there are at least 2 horizontal and 2 vertical guides.");
}
} else {
alert("No document is open.");
}
// Functions
function getGuides(doc) {
var guides = doc.guides;
var horizontalGuides = [];
var verticalGuides = [];
for (var i = 0; i < guides.length; i++) {
if (guides[i].direction == Direction.HORIZONTAL) {
horizontalGuides.push(guides[i].coordinate.as('px'));
} else {
verticalGuides.push(guides[i].coordinate.as('px'));
}
}
return {horizontal: horizontalGuides, vertical: verticalGuides};
}
function newGuideLayout(marginTop, marginLeft, marginBottom, marginRight) {
app.preferences.rulerUnits = Units.PERCENT;
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor.putBoolean(s2t("replace"), true); // true or false boolean
descriptor.putEnumerated(s2t("presetKind"), s2t("presetKindType"), s2t("presetKindCustom"));
descriptor2.putUnitDouble(s2t("marginTop"), s2t("percentUnit"), marginTop);
descriptor2.putUnitDouble(s2t("marginLeft"), s2t("percentUnit"), marginLeft);
descriptor2.putUnitDouble(s2t("marginBottom"), s2t("percentUnit"), marginBottom);
descriptor2.putUnitDouble(s2t("marginRight"), s2t("percentUnit"), marginRight);
descriptor2.putInteger(c2t("GdCA"), 0); // ?
descriptor2.putInteger(c2t("GdCR"), 74); // Red value
descriptor2.putInteger(c2t("GdCG"), 255); // Green value
descriptor2.putInteger(c2t("GdCB"), 255); // Blue value
descriptor.putObject(s2t("guideLayout"), s2t("guideLayout"), descriptor2);
descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetCanvas"));
executeAction(s2t("newGuideLayout"), descriptor, interactive);
}
function cropToSelection(top, left, bottom, right, retainPixels) {
// Courtesy of Chuck Uebele
app.preferences.rulerUnits = Units.PIXELS;
var idCrop = charIDToTypeID("Crop");
var desc11 = new ActionDescriptor();
var idT = charIDToTypeID("T ");
var desc12 = new ActionDescriptor();
var idTop = charIDToTypeID("Top ");
var idPxl = charIDToTypeID("#Pxl");
desc12.putUnitDouble(idTop, idPxl, top);
var idLeft = charIDToTypeID("Left");
var idPxl = charIDToTypeID("#Pxl");
desc12.putUnitDouble(idLeft, idPxl, left);
var idBtom = charIDToTypeID("Btom");
var idPxl = charIDToTypeID("#Pxl");
desc12.putUnitDouble(idBtom, idPxl, bottom);
var idRght = charIDToTypeID("Rght");
var idPxl = charIDToTypeID("#Pxl");
desc12.putUnitDouble(idRght, idPxl, right);
var idRctn = charIDToTypeID("Rctn");
desc11.putObject(idT, idRctn, desc12);
var idAngl = charIDToTypeID("Angl");
var idAng = charIDToTypeID("#Ang");
desc11.putUnitDouble(idAngl, idAng, 0.000000);
var idDlt = charIDToTypeID("Dlt ");
desc11.putBoolean(idDlt, retainPixels); // delete cropped pixels = true | false
var idcropAspectRatioModeKey = stringIDToTypeID("cropAspectRatioModeKey");
var idcropAspectRatioModeClass = stringIDToTypeID("cropAspectRatioModeClass");
var idtargetSize = stringIDToTypeID("targetSize");
desc11.putEnumerated(idcropAspectRatioModeKey, idcropAspectRatioModeClass, idtargetSize);
executeAction(idCrop, desc11, DialogModes.NO);
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
Many thanks!
I'll reply again once I try this out.
Copy link to clipboard
Copied
Many thanks!
I'll reply again once I try thsi out.
By @Mark37430984r9lw
You're welcome, I have updated the code to a 1.2 version as there were some unexpected results in the crop with different ruler units. I believe that I have now overcome this issue.
Copy link to clipboard
Copied
How does one edit their own posts here? I want to correct the spelling in my previous reply, but do not see an "edit" botton anywhere.
Copy link to clipboard
Copied
"How does one edit their own posts here" you need a certain amount of post before you can edit your own, not sure what that number is though
Copy link to clipboard
Copied
I want to correct the spelling in my previous reply
By @Mark37430984r9lw
I changed "thsi" to "this" for you.
Jane
Copy link to clipboard
Copied
Stephen,
This is PERFECT! Exactly what I was looking for. I really like the forms where I can change the percentages on the fly without having to hand edit the jsk file and re-run.
Much appreciated.
Have a good night!
Mark
Copy link to clipboard
Copied
You're welcome.
Once you know what the common/average % margins are, you can update these values in the script and disable the interactive step to record the script into a batch action. Also note the true/false boolean to delete or retain the cropped pixels.
Copy link to clipboard
Copied
I copied over two scripts to the appropriate directory. One as written, and the other changing All to NO for batch processing as per your instructions here:
Change ALL to NO to disable interactivity when batching
var interactive = DialogModes.ALL;
I've been searching for a while, but can't figure how to batch process using this script. It would be easier to have a form open and allow me to choose a source directory and destination one. I found documentation regarding recording an action, but when I open the action window, the play button is disabled.
How do I setup batch processing with this. One I input the data, I would of course want everything auto-saved.
Copy link to clipboard
Copied
Open an image.
Create a new Action Set. Add a new Action, the record button will be active.
If the script is installed in the Presets/Scripts folder, then the script will be listed under File > Scripts. Run the script. Otherwise, use File > Scripts > Browse to select and run the script.
After the Script has run, stop recording the Action.
https://helpx.adobe.com/photoshop/using/creating-actions.html
Then use File > Automate > Batch and select the Action Set and Action.
https://helpx.adobe.com/photoshop/using/processing-batch-files.html
Copy link to clipboard
Copied
Getting closer. Now, when I use file - automate - batch and select the batch set and options, it runs, however, for each jpg in the source directory, I am prompted for the file name, and it defaults to a PSD extension which I have to change to jpg. Then, the jpg options come up for the save. Selecting either or both of the Override action "open" and Override action "save as" selectons just disables the output. The "save as" button on the bottom lest if grayed out.
I want this to run and auto-save everything as the highest quality (12) jpg in the destination directory using whatever naming convention I choose in the menu without any prompts.
How can I accomplish this?
Copy link to clipboard
Copied
Minor correction. I just want everything auto-saved in the destination folder using the original file names.
Copy link to clipboard
Copied
If you check the override box for open or save, the action step must have a corresponding open or save step in it to override.
Copy link to clipboard
Copied
I saw those descriptions when hovering over the options. I had oiginally followed your instructions by recording the action set and then running the variant of your script with this code:
// Change ALL to NO to disable interactivity when batching
var interactive = DialogModes.NO;
I then stopped the recording.
How do I need to tweak the process in order to get the automation to run to auto-save the highest quality jpgs in the destination directory, using the original file names, and without any prompts?
Copy link to clipboard
Copied
How do I need to tweak the process in order to get the automation to run to auto-save the highest quality jpgs in the destination directory, using the original file names, and without any prompts?
By @Mark37430984r9lw
Your Action would have the Script step and a Save a Copy JPEG step and the Batch could be set similarly to this screenshot:
EDIT: I forgot to mention File > Scripts > Image Processor, which can save to JPEG and run an Action. This is one alternative to creating an Action and using the Batch command.
Copy link to clipboard
Copied
I got the full automation working after also recording the last step of me saving the jpg as the highest quality.
There are times when I come home from birdwatching sessions and have a lot of sets of 7-shot bursts that that I’m going to want to crop. You have no idea how much post-processing time you saved me. In addition, the output of similar shots will now be standardized.
Have a good day!