Photoshop Scripting – Batch resizing image size and image canvas

Later today, a friend of mine was editing some images and I’ve noticed that he was repeating the same process again and again… open the image… resize the width to 720 pixels… selecting a matching background colour (because when resizing canvas, bars on top and bottom of the image were being added) and resize canvas so the image had the expected 720 x 1024.

After 15 minutes I asked him what he was doing. He had more than 200 files to process. If it took 1 min (I believe he was taking longer) to process each file, he was gonna take more than 3 hours to complete it. And when new images become available, he would once again repeat the same process again…

Below, an example of what he was doing.

Original image example:

(Original image downloaded from http://www.shunvmall.com)

This image’s original dimension was 1000 x 750 so he needed to resize the image to 720 x 540, choose the background color that the top/bottom added bars should have (black was used in this case) and then resize the canvas to 720 x 1024.

This is the final image, with the expected dimensions (720 x 1024).

So I thought… “hum… let’s get to work and make this guy happy!”.

First I tried to use Photoshop Actions but it wouldn’t work because I couldn’t automatically define the background color to be used in each image, otherwise that would be the fastest and easiest way to do this.

So I moved to Photoshop scripting. This allows you to make almost everything, including to check the color of the pixel in the top left corner of the image to be used as the background colour. This way  the colour of the added bars matches the original image’s colours 🙂

I share with you the script I’ve created and used. Please let me know if you have any doubts.

#target photoshop
app.preferences.rulerUnits = Units.PIXELS;

if (app.documents.length > 0)
{
alert (“Please close all open documents before running this script.”);
} else {

// The width and height I wanted to consider. You may have to change this to make it dynamic.
var finalWidth = 720;
var finalHeight = 1024;

//The file suffix to add to the new files, if you want to.
var fileSuffix = “_new”;

// Use folder selection dialogs to get the location of the input files
// and where to save the new output files.
var sourceFolder = Folder.selectDialog (“Please choose the location of the source image files.”, Folder.myDocuments);
var destFolder = Folder.selectDialog (“Please choose a location where the new image files will be saved.”, sourceFolder);

// Consider only some images filetypes.
var files = sourceFolder.getFiles(/.+\.(?:jpe?g|bmp|png)$/i);
var nrOfFiles = files.length;

for (var i = 0; i < files.length; i++)
{
var f = files[i];

if (f instanceof Folder)
continue;

var docRef = app.open (f);
var layerRef = docRef.activeLayer;

//Image resize
var actualWidth = docRef.width;
var actualHeight = docRef.height;
var newHeight = finalWidth * actualHeight / actualWidth;

docRef.resizeImage(finalWidth,newHeight);

//Get top left pixel color to use as background color
for (var j = 0; j < docRef.colorSamplers.length; j++) {
docRef.colorSamplers[j].remove();
}
var sampler = docRef.colorSamplers.add([0, 0]);

//Set the background color
app.backgroundColor = sampler.color;

//Resize canvas
docRef.resizeCanvas(finalWidth, finalHeight, AnchorPosition.MIDDLECENTER);

//Get filename and extension to use it when saving.
var fileExtension = getFileExtension(f.name);
var filename = getFilename(f.name);

var outputFile = new File (destFolder.absoluteURI + “/” + filename + fileSuffix + “.” + fileExtension);
saveAsJPG(docRef, outputFile, 8);

docRef.close ();
}

alert(nrOfFiles + ” files have been processed.”);
}

function getFileExtension (fullFilename) {
return fullFilename.split(‘.’).pop();
}

function getFilename (fullFilename) {
var finalDotPosition = fullFilename.lastIndexOf(“.”) ;

if ( finalDotPosition > -1 ) {
return fullFilename.substr( 0 , finalDotPosition );
}
return fullFilename;
}

function saveAsJPG(docRef, saveFile, jpegQuality) {
options = new JPEGSaveOptions();
options.quality = jpegQuality;
docRef.saveAs(saveFile, options, false,Extension.LOWERCASE);
}

Share this

6 Comments

  1. The setting of the background colour and canvas resize call was exactly what I needed to escape my google-results-nightmare of layer manipulations and layer fills. It just seemed like there had to be an easier way to add some colour borders… and then I found your post.

    Very helpful, thank you!

  2. thanks for the post, it’s a great starting point.
    Being new, I wanted to ask you how does that code run?
    Do you save that code in a .bat file?
    Can you feed him a whole folder of images? also subfolders?

    Thanks
    Diego

    • Hi Diego,

      Thanks for your comment.
      It’s been a while since I wrote this post. I’m not near to my computer but as far as I remember, you can save the script I wrote to a jsx file and then execute it on Photoshop going to File -> Scripts -> Browse.
      I’ve used Javascript but Photoshop also accepts Applescript, for example, in case you’re used to it.
      In the script there is a piece of code that will open a dialog window so that you can select the source folder you want to process as well as the destination folder to where the updated files with be saved.

      var sourceFolder = Folder.selectDialog (“Please choose the location of the source image files.”, Folder.myDocuments);
      var destFolder = Folder.selectDialog (“Please choose a location where the new image files will be saved.”, sourceFolder);

      In my scenario I was not processing subfolders. That’s why I have this piece of code:

      if (f instanceof Folder)
      continue;

      If you want to process subfolders as well, then you need to replace the code below and create a loop to read all the files inside the folder, whenever a folder is found.
      You would need to call this piece of code again but instead of the sourceFolder variable, you would use the f variable.

      var files = sourceFolder.getFiles(/.+\.(?:jpe?g|bmp|png)$/i);
      var nrOfFiles = files.length;
      for (var i = 0; i < files.length; i++) { var f = files[i];

      The code should be refactored a little bit to avoid duplicated code and variables conflict.
      If you have some development knowledge you should have no problems to do it.

      Please let me know if you need further help.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.