Conditional Image Resizing with Photoshop and JavaScript
Often I find myself having to do a lot of bulk image processing when I'm working on websites: resizing a bunch of pictures to a certain width or height, color adjustments, and sharpening, usually. It can be the most mind-numbing part of my work, and I'm always looking for ways to avoid that.
In Photoshop, you can use actions to help you automate a lot of repetitive work. However, the shortcoming I've found with actions is their lack of conditional behavior. For example, let's say I have a big batch of images, some portrait-oriented (taller than they are wide) and some landscape-oriented (vice versa), and I want to resize each of them to fit within a 500 x 500 pixel square. If the image is portrait-oriented, then I need to resize proportionally, setting the height to 500 pixels. If it's landscape-oriented, then I should resize proportionally with a 500 pixel width, instead of height. I've never found a good way to do this with a single action. But where actions fail, JavaScript comes to the rescue.

Resizing portrait- and landscape-oriented images to fit within a square space.
About Scripts in Photoshop
Photoshop CS2 provides a way to write scripts in JavaScript (and AppleScript, but I'm not going to cover that here) to automate all kinds of behavior. What follows is a run-through of a basic script for Photoshop CS2 for doing conditional resizing of images, as well as some basic cleanup and export.
First, a brief intro to how to set up a script for Photoshop CS2. Create a file in a text editor called "Image Resize and Export.jsx", and save it in your Photoshop CS2 Presets/Scripts folder. On my mac, that folder is located at /Applications/Photoshop CS2/Presets/Scripts. This file is where we'll be putting the code that follows. For a text editor, you might look and see if you have ExtendScript Toolkit installed. This is a special editing program made by Adobe for scripting Photoshop (and Illustrator, InDesign, etc.). Once you have your script saved in the right folder, you'll be able to select it in Photoshop via a menu by going to File → Scripts → Image Resize and Export. If Photoshop was already open when you first saved the script file, you'll need to restart Photoshop to make the script appear in the Scripts menu.
The Code
So, on to the code. The script we're making here is going to operate on the current document in Photoshop (that is, the one that's selected when we run the script). I like setting a shortcut key for the script once I have it ready (via Edit → Keyboard Shortcuts...), so that all it takes is a single keypress to resize the current image, clean it up, and save it in a web-ready form.
Anyway, let's do the resizing of the image. Here's the code, with comments about what's going on:
// get a reference to the current (active) document and store it in a variable named "doc"
doc = app.activeDocument;
// change the color mode to RGB. Important for resizing GIFs with indexed colors, to get better results
doc.changeMode(ChangeMode.RGB);
// these are our values for the end result width and height (in pixels) of our image
var fWidth = 500;
var fHeight = 500;
// do the resizing. if height > width (portrait-mode) resize based on height. otherwise, resize based on width
if (doc.height > doc.width) {
doc.resizeImage(null,UnitValue(fHeight,"px"),null,ResampleMethod.BICUBIC);
}
else {
doc.resizeImage(UnitValue(fWidth,"px"),null,null,ResampleMethod.BICUBIC);
}
So far, this will give us a resized image that fits within a 500-pixel square (change the dimensions in the code to suit your needs). Now that the image is resized, let's apply some auto-contrast, and sharpen the image (often images get a little fuzzy when you reduce their size a good bit):
// call autoContrast and applySharpen on the active layer.
// if we just opened a gif, jpeg, or png, there's only one layer, so it must be the active one
doc.activeLayer.autoContrast();
doc.activeLayer.applySharpen();
Finally, let's export the image as a JPEG, at 70 quality. The file we save will be named based on the original file, with "web-" prepended to the name:
// our web export options
var options = new ExportOptionsSaveForWeb();
options.quality = 70;
options.format = SaveDocumentType.JPEG;
options.optimized = true;
var newName = 'web-'+doc.name+'.jpg';
doc.exportDocument(File(doc.path+'/'+newName),ExportType.SAVEFORWEB,options);
The resized, optimized version of our image is now saved in the same directory as the original file, with "web-" at the beginning of the file name.
The Whole Thing
Here's the script in its entirety, for easy copy and paste:
// get a reference to the current (active) document and store it in a variable named "doc"
doc = app.activeDocument;
// change the color mode to RGB. Important for resizing GIFs with indexed colors, to get better results
doc.changeMode(ChangeMode.RGB);
// these are our values for the end result width and height (in pixels) of our image
var fWidth = 500;
var fHeight = 500;
// do the resizing. if height > width (portrait-mode) resize based on height. otherwise, resize based on width
if (doc.height > doc.width) {
doc.resizeImage(null,UnitValue(fHeight,"px"),null,ResampleMethod.BICUBIC);
}
else {
doc.resizeImage(UnitValue(fWidth,"px"),null,null,ResampleMethod.BICUBIC);
}
// call autoContrast and applySharpen on the active layer.
// if we just opened a gif, jpeg, or png, there's only one layer, so it must be the active one
doc.activeLayer.autoContrast();
doc.activeLayer.applySharpen();
// our web export options
var options = new ExportOptionsSaveForWeb();
options.quality = 70;
options.format = SaveDocumentType.JPEG;
options.optimized = true;
var newName = 'web-'+doc.name+'.jpg';
doc.exportDocument(File(doc.path+'/'+newName),ExportType.SAVEFORWEB,options);
Update: Thanks to Hreinsson for pointing out that I was not specifying a unit when resizing images. The script has been updated now to resize in units of pixels!
Comments
In my Photoshop CS4 this resizes the picture to fit within 500x500cm, not pixels!
Hi Hreinsson, thanks for pointing that out... it should be fixed now. The problem was that the script was not specifying units for the resize operation. When you don't specify a unit, Photoshop will assume the number you give it has the default unit that is set in your Preferences.
The solution is to pass a UnitValue object, like so:
I had to make a similar fix awhile back on another script I wrote: Thumbnail Generation with Photoshop and JavaScript.
Thanks again!
Hi,
Wondering if theres any way of designating a specific export folder as opposed to the "web-" prefix dealio.
Would love it if you could email me as opposed to replying to this as I might lose the page.
Thanks so far.
Ryan, the last 2 lines are what you would change to specify an export folder. Instead of:
... you would do something like:
Hope you can find this page again!
I found it! (Save it in the end, no doubt be using this page a lot from now on) Thanks for the help.
Another query, due to my inexperience with photoshop and scripting in general I'm trying to run a script to run an action to run a script, at which point it doesn't allow me to presumably because you can only run one script at a time.
Let me break it down a little further. I'm using the "Image Processor" built in script, which also runs an action I made, which in turn runs part of the script on this page.
Am I over-confusing things? Should I google some more? Thanks Chadwick, Ryan
Oh and I've also been messing around with adding one of my scripts to edit the current canvas to include '-drawing' in the title once it saves the document but no luck there whatsoever.
I'm learning surely, but super slowly. :D
I'm sorry to say I'm not familiar with integrating scripts with actions. The only advice I can give is to see if you can eliminate the action part of your process, and just do it all in a script. Of course, I don't know what your action is, and some things just aren't possible in scripts, unfortunately. But that's the best I've got. Good luck!
Loved the script. Made it easy for me to save files quickly without needing to check dimensions everytime!
Great work on the script! I've used this before and it's ideal.
I wanted to let you know, however, that I've just gotten CS5, and there's a new option in the menu to do this: File > Automate > Fit Image... Using this, you can create an action that fits the image within a certain size and saves it out to another folder without any scripting.
Thanks for the heads up, Caleb. Maybe someday I'll get my hands on CS5 :)
No kidding, I have it at work, but can't justify the $$ to upgrade at home. In the meantime, your script will be my goto at home.
Thanks, C
Thanks a lot
I was wondering what would have to be done to apply this script to a file of images i have about 100,000+ images i need to do this with and it seems to work, please forgive me i am new to Javascript
Make a new action and record you running the script. Then go to File > Automate > Batch, select your new action, choose source (probably folder), and destination (none, if saving is done in the script or in the action).
Would it be possible to modify this so it asks you what size you want the final image at the beginning instead of hard coding the size into the script?
That should be possible, but I'm going to leave that as an exercise for the reader :)
"That should be possible, but I'm going to leave that as an exercise for the reader :)"
Damn I knew you were going to say that! If anyone stumbles on this and knows how to do it can you let me know :)
Nice script!
I was wondering if there is a way to save the image in a new folder that will be created in the script?
I have tried this:
doc.exportDocument(File(doc.path+'/NEW_FOLDER_NAME/'+newName),ExportType.SAVEFORWEB,options);
but unfortunately this does not work for me..
Hi, thanks for the breakdown. Do you know a script to batch process to make all horizontal or all vert? the source is a mix of vertical and horizontal - about 30,000 images that will be sent in smaller batches. I do not want to use bridge to sort, too time consuming.
Am I right that if an image is portrait-oriented that the height is 500 and the width is less? Or does this script generate automaticly a white background and does it fills teh wide up to 500px?
Tiby, that's right. No automatic fill for the background.
Add new comment