1

The scenario

I often have Photoshop files with the following general Layers configuration (each item is a Layer Group):

  • Output 1
  • Output 2
  • Output 3
  • Background Group

This example would produce three different images. Each will include the Background Group combined with one of the Output n groups.

My current workflow

My current workflow requires me to export (Save for web...) each of these output images, in a range of sizes (based on image width). They are:

  • 150px
  • 400px
  • 600px
  • 800px
  • 1200px

All are exported as .jpg files with a quality setting of 60.

Those dimensions could vary in other situations, but for the current file those are the output sizes.

The image I am currently working with is square, but there are situations where it may be rectangular.

Currently, each time I make changes to the Background Group I have to manually export 5 x 3 images. That's 15 operations. It's taking me a lot of time, so I figure there must be a way to automate it.

My Question

I would like to know how to best go about automating this.

I have found other related solutions, both here and on other blogs posts and Adobe forums. But they either focus on exporting each layer (one layer = one image), or exporting an entire PSD file to multiple output sizes.

What I found that was similar to my requirements

This script on Github exports every individual layer to an image, but not layer groups, and it doesn't allow for a batch of different output sizes).

I also found the xtools scripts, which look very useful, but it doesn't allow for exports based on layer groups. Otherwise, it looks like a very hand tool.

My specific requirements are:

  1. One-by-one combine each group with the Background Group.
  2. Generate multiple files sizes
  3. Name those files accordingly (layer-name-[width].jpg)
  4. Ideally the solution would allow me to customise it for different output sizes. So that it's not locked in to only export the sizes mentioned above.

  5. At the very least, it would be great to be able to simply export a batch of files sizes, to set format (JPG or PNG), at a set quality, using a merge of all visible layers. That would at least cut this example task down to three actions (one per Output n layer).

Photoshop Image Processor Pro does at least allow a way to partly achieve #5. I can export the necessary image dimensions (one layer group at a time). Although, I see no way to include the image dimensions (width and/or height) in the file naming, nor the layer name. Which means there will be an added step of manually renaming each file according to its size, and corresponding Output n layer name. It does still require me to do each layer group combination one-by-one.

Can anyone suggest how to go about this?

Thank you.

1

What you need is a script to do the work for you. In the script you need: an array to hold the current widths that you are shrinking to Loop over that array duplicate the source image shrink that source image to the specified size rename it (imagename_newwidth.jpg) close it

I'm confused by your exact specific requirements at the bottom of your question. However, the script below will give you a point to start from (your current work flow):

//pref pixels
app.preferences.rulerUnits = Units.PIXELS;

// call the source document
var srcDoc = app.activeDocument;

// set the jpeg quality
var myJpgQuality = 6;

// name the file name after the source file but remove the extension
var fName = app.activeDocument.name;
var docName = fName.substring(0, fName.lastIndexOf("."));

// define the array to hold the sizes of the shrunk images
var sizeArray = [
1200,
800,
600,
400,
150
]

/// main loop for shrinking images
for (var i = 0; i < sizeArray.length; i++)
{
  var shrinkWidth = sizeArray [i];

  var mySaveName = docName + "_" + shrinkWidth;

  // duplicate the source image
  duplicateIt(mySaveName);

  // resize it according to width
  scaleWithStyle(shrinkWidth, true, "Wdth");

  // Set filePath and fileName to source path
  var filePath = srcDoc.path + "/" + mySaveName + ".jpg";

  // Save it!
  saveAsJpeg(filePath);

  // Close it!
  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
} // loop over icon array (i)


function duplicateIt(str)
{
  // duplicate image into new document
  if (arguments.length == 0) str = "temp";

  var id428 = charIDToTypeID( "Dplc" );
  var desc92 = new ActionDescriptor();
  var id429 = charIDToTypeID( "null" );
  var ref27 = new ActionReference();
  var id430 = charIDToTypeID( "Dcmn" );
  var id431 = charIDToTypeID( "Ordn" );
  var id432 = charIDToTypeID( "Frst" );
  ref27.putEnumerated( id430, id431, id432 );
  desc92.putReference( id429, ref27 );
  var id433 = charIDToTypeID( "Nm  " );
  desc92.putString( id433, str ); // name
  executeAction( id428, desc92, DialogModes.NO );
}


function scaleWithStyle(input, style, widthOrHeight)
{
   var id01 = charIDToTypeID( "ImgS" );
   var desc = new ActionDescriptor();
   var id02 = charIDToTypeID( widthOrHeight ); // "Wdth" or "Hght" 
   var id03 = charIDToTypeID( "#Pxl" );
   desc.putUnitDouble( id02, id03, input );
   var id04 = stringIDToTypeID( "scaleStyles" ); //scale styles
   desc.putBoolean( id04, style );        //scale styles
   var id05 = charIDToTypeID( "CnsP" );   // constrain proportions
   desc.putBoolean( id05, true );      // constrain proportions
   var id06 = charIDToTypeID( "Intr" );
   var id07 = charIDToTypeID( "Intp" );
   var id08 = charIDToTypeID( "Bcbc" );
   desc.putEnumerated( id06, id07, id08 );
   executeAction( id01, desc, DialogModes.NO );
}


function saveAsJpeg(filePath, myJpgQuality)
{
  if(! myJpgQuality) myJpgQuality = 12;

  // Flatten the jpg
  activeDocument.flatten();

  // jpg file options
  var jpgFile = new File(filePath);
  jpgSaveOptions = new JPEGSaveOptions();
  jpgSaveOptions.formatOptions = FormatOptions.OPTIMIZEDBASELINE;
  jpgSaveOptions.embedColorProfile = true;
  jpgSaveOptions.matte = MatteType.NONE;
  jpgSaveOptions.quality = myJpgQuality;

  activeDocument.saveAs(jpgFile, jpgSaveOptions, true, Extension.LOWERCASE);
}

function mergeDown()
{
  app.activeDocument.activeLayer.merge();
}
  • Wow. The magic of script writing. Thanks for this. Will test and fiddle with this when at my computer. If you let me know ow which part of my requirements was unclear, I'll do what I can to clarify. Looking at the script, I gather I need to make visible each top and bottom layer combo and the run the script. Correct? So, in the case of the example I gave, I'd run the script 3 time. Once for output 1, 2 and 3 (each with the background group. Is that correct? – inspirednz Sep 7 '17 at 20:29
  • Hi there. I've been testing out this script. Unfortunately it doesn't appear to be working, and I know so little about JS that it's not something I can fiddle much with (not without messing it up). When I run this script Photoshop "flashes" 5 times, as though it is processing each of the 5 output sizes. But I don't see any new files anywhere, so it would appear there's no actual output. Also, it's not clear to me what I must do in the image. Make visible each layer set pair, and then run the script? – inspirednz Sep 14 '17 at 10:11
  • Actually, my mistake. The second time I run it, there are new files generated. Does PS JSX allow for grabbing a layer name? Such as the uppermost visible layer? – inspirednz Sep 14 '17 at 10:16
  • yeah, it's easy just use app.activeDocument.activeLayer = app.activeDocumentc.artLayers.getByName(myLayerName); where myLayername is the variable holding the name the layer you're after; otherwise use quotes "Layer 1" – Ghoul Fool Sep 16 '17 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.