Copy link to clipboard
Copied
Hi, I am trying to batch export 4 different variants of 12 files at 3 different scales.
Each file has 4 different layer comps. I need each file to be exported at 300 DPI, 144 DPI, and 72 DPI as JPGs. Finally, I need to do this for 12 different files which as you can imagine is extremely tedious.
I have tried all of the following methods:
How to both export and resize layer comps?
Here is a batch version:
/*
Batch All Layer Comps x3 Sizes to JPEG.jsx
v1.1, 15th May 2024 - Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-both-export-and-resize-layer-comps/td-p/14614232
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/droplets-and-export-layer-comps-to-files/td-p/14585398
https://community.adobe.com/t5/photoshop-ecosystem-discussions/a-script-that-would-pack-layercomps-into-rgba-channels-and-savi...
Copy link to clipboard
Copied
If all of the 12 files use the same names for the layer comps, then you might be able to use an action, however, you'll probably need a custom script for the filenames.
What are the pixel dimensions of the PSD file with the comps? Is this to be considered the 300ppi file?
So as an example, if the master doc was 1200x1200px @ 300ppi in size, would the 144ppi version be 576x576px in final size, with the 72ppi version being 288x288px in size?
How would the files be named? Something like the following?
DocumentName_LayerCompName_300ppi.jpg
DocumentName_LayerCompName_144ppi.jpg
DocumentName_LayerCompName_72ppi.jpg
Or something else?
Copy link to clipboard
Copied
Hi!
To answer your questions and clarify a bit:
Thank you for your help so far!
Copy link to clipboard
Copied
So to be clear:
5760x5760px @ 144ppi
2880x2880px @ 72ppi
Yes, you need to setup the comps in all 12 files as I have no idea of your layers or intent.
Is it just this one project of 4 comps x 12 files x 3 sizes per file, or is this an ongoing requirement?
Copy link to clipboard
Copied
Yes, those resolutions are correct.
This is an ongoing requirement. All projects consistently require the 4 versions and 3 different PPIs. The number of total files needing this varies however.
Thank you again for your help so far!
Copy link to clipboard
Copied
How do the 4 versions come into play?
Can you show a screenshot of the layers panel for one file?
I am trying to understand this project, sight unseen. I feel that there are undisclosed traps for programming...
Copy link to clipboard
Copied
Of course, here is a snapshot of the layers that are different between each comp within a single file.
The layers outlined in red are toggled between each comp. So for each of the four comps, the combinations are:
Each of the twelve files consistently has these configurations. I hope that makes sense!
Copy link to clipboard
Copied
OK, I don't need to worry about the layer structure then if your comps reflect the required visibility to produce as many versions as you require at the 3 resolutions.
Copy link to clipboard
Copied
Glad to hear! That should hopefully make a solution easier.
Copy link to clipboard
Copied
Try the following script, it will save the 3 sizes for each comp to a folder on the Desktop called "JPEG_Comps".
This script only works on a single open doc. You can just run it once for each doc you need to process, or extra code can be added to batch process a folder of files. There isn't any point in extending this for batch processing until it is confirmed that this is working as required.
/*
All Layer Comps x3 Sizes to JPEG.jsx
v1.0, 13th May 2024 - Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-both-export-and-resize-layer-comps/td-p/14614232
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/droplets-and-export-layer-comps-to-files/td-p/14585398
https://community.adobe.com/t5/photoshop-ecosystem-discussions/a-script-that-would-pack-layercomps-into-rgba-channels-and-saving-in-chosen-file-format/m-p/13906491
*/
#target photoshop
if (documents.length > 0) {
if (activeDocument.layerComps.length) {
app.togglePalettes();
var restoreDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
try {
//var theSavePath = Folder.selectDialog("Select the output folder:");
var theSavePath = Folder('~/Desktop/JPEG_Comps');
if (!theSavePath.exists) {
theSavePath.create();
}
} catch (e) {
var theSavePath = Folder('~/Desktop/');
}
deleteDocumentAncestorsMetadata();
removeCRSmeta();
removeXMP();
// 300 ppi
activeDocument.resizeImage(activeDocument.width.value, activeDocument.height.value, 300, null);
for (i = 0; i < activeDocument.layerComps.length; i++) {
activeDocument.layerComps[i].apply();
var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_300ppi_" + compName + ".jpg");
saveCompToJPG();
}
// 144 ppi
app.activeDocument.duplicate(docName, false);
activeDocument.resizeImage(null, null, 144, ResampleMethod.BICUBIC);
for (i = 0; i < activeDocument.layerComps.length; i++) {
activeDocument.layerComps[i].apply();
var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_144ppi_" + compName + ".jpg");
saveCompToJPG();
}
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
// 72 ppi
activeDocument.resizeImage(null, null, 72, ResampleMethod.BICUBIC);
for (i = 0; i < activeDocument.layerComps.length; i++) {
activeDocument.layerComps[i].apply();
var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_72ppi_" + compName + ".jpg");
saveCompToJPG();
}
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
app.togglePalettes();
app.displayDialogs = restoreDialogMode;
} else {
alert("The document must contain layer comps!");
}
} else {
alert("You must have a document open!");
}
function saveCompToJPG() {
try {
var jpgOptns = new JPEGSaveOptions();
jpgOptns.formatOptions = FormatOptions.STANDARDBASELINE;
jpgOptns.embedColorProfile = true;
jpgOptns.matte = MatteType.NONE;
jpgOptns.quality = 10;
activeDocument.saveAs(filePath, jpgOptns, true, Extension.LOWERCASE);
} catch (e) {
alert("Error!" + "\r" + e + ', Line: ' + e.line);
}
}
function removeXMP() {
//https://community.adobe.com/t5/photoshop/script-to-remove-all-meta-data-from-the-photo/td-p/10400906
if (!documents.length) return;
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
XMPUtils.removeProperties(xmp, "", "", XMPConst.REMOVE_ALL_PROPERTIES);
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function removeCRSmeta() {
//community.adobe.com/t5/photoshop/remove-crs-metadata/td-p/10306935
if (!documents.length) return;
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
XMPUtils.removeProperties(xmp, XMPConst.NS_CAMERA_RAW, "", XMPConst.REMOVE_ALL_PROPERTIES);
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function deleteDocumentAncestorsMetadata() {
whatApp = String(app.name); //String version of the app name
if (whatApp.search("Photoshop") > 0) { //Check for photoshop specifically, or this will cause errors
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
// Begone foul Document Ancestors!
xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
Thank you for creating this script! I'll give it a test run and let you know how it goes.
Copy link to clipboard
Copied
Just tested and can confirm it worked flawlessly. Thank you for your help so far!
Copy link to clipboard
Copied
Just tested and can confirm it worked flawlessly. Thank you for your help so far!
By @Jamie Squared
You're welcome, I'll look at adding batch processing code now that I know that this works for you.
P.S. The current script could be recorded into an action, and then the batch command can be used to process multiple files.
Copy link to clipboard
Copied
Here is a batch version:
/*
Batch All Layer Comps x3 Sizes to JPEG.jsx
v1.1, 15th May 2024 - Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-both-export-and-resize-layer-comps/td-p/14614232
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/droplets-and-export-layer-comps-to-files/td-p/14585398
https://community.adobe.com/t5/photoshop-ecosystem-discussions/a-script-that-would-pack-layercomps-into-rgba-channels-and-saving-in-chosen-file-format/m-p/13906491
*/
#target photoshop
(function () {
var inputFolder = Folder.selectDialog("Please select the input folder:");
// Test if Cancel button returns null, then do nothing
if (inputFolder === null) {
app.beep();
return;
}
var outputFolder = Folder.selectDialog("Please select the output folder:");
// Test if Cancel button returns null, then do nothing
if (outputFolder === null) {
app.beep();
return;
}
var fileList = inputFolder.getFiles(/\.(psd|psb|tif|tiff)$/i);
//alert(fileList.length + " files will be processed...");
var theConfirmation = (confirm(fileList.length + " source files will be processed. Continue?", false));
// Test if the No button returns false, then do nothing
if (theConfirmation === false) {
app.beep();
return;
}
app.togglePalettes();
var restoreDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
var fileCounter = 0;
for (var l = 0; l < fileList.length; l++) {
open(fileList[l]);
if (app.activeDocument.layerComps.length) {
try {
//var theSavePath = Folder.selectDialog("Select the output folder:");
var theSavePath = Folder('~/Desktop/JPEG_Comps');
if (!theSavePath.exists) {
theSavePath.create();
}
} catch (e) {
var theSavePath = Folder('~/Desktop/');
}
deleteDocumentAncestorsMetadata();
removeCRSmeta();
removeXMP();
// 300 ppi
app.activeDocument.resizeImage(app.activeDocument.width.value, app.activeDocument.height.value, 300, null);
for (i = 0; i < app.activeDocument.layerComps.length; i++) {
app.activeDocument.layerComps[i].apply();
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = app.activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_300ppi_" + compName + ".jpg");
saveCompToJPG();
}
// 144 ppi
app.activeDocument.duplicate(docName, false);
app.activeDocument.resizeImage(null, null, 144, ResampleMethod.BICUBIC);
for (i = 0; i < app.activeDocument.layerComps.length; i++) {
app.activeDocument.layerComps[i].apply();
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = app.activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_144ppi_" + compName + ".jpg");
saveCompToJPG();
}
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
// 72 ppi
app.activeDocument.resizeImage(null, null, 72, ResampleMethod.BICUBIC);
for (i = 0; i < app.activeDocument.layerComps.length; i++) {
app.activeDocument.layerComps[i].apply();
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var compName = app.activeDocument.layerComps[i].name.replace(/\.[^\.]+$/, '');
var filePath = new File(theSavePath + "/" + docName + "_72ppi_" + compName + ".jpg");
saveCompToJPG();
}
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
} else {
//alert("The document must contain layer comps!");
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
///// Functions /////
function saveCompToJPG() {
try {
var jpgOptns = new JPEGSaveOptions();
jpgOptns.formatOptions = FormatOptions.STANDARDBASELINE;
jpgOptns.embedColorProfile = true;
jpgOptns.matte = MatteType.NONE;
jpgOptns.quality = 10;
app.activeDocument.saveAs(filePath, jpgOptns, true, Extension.LOWERCASE);
fileCounter++;
} catch (e) {
alert("Error!" + "\r" + e + ', Line: ' + e.line);
}
}
function removeXMP() {
//https://community.adobe.com/t5/photoshop/script-to-remove-all-meta-data-from-the-photo/td-p/10400906
if (!documents.length) return;
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
XMPUtils.removeProperties(xmp, "", "", XMPConst.REMOVE_ALL_PROPERTIES);
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function removeCRSmeta() {
//community.adobe.com/t5/photoshop/remove-crs-metadata/td-p/10306935
if (!documents.length) return;
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
XMPUtils.removeProperties(xmp, XMPConst.NS_CAMERA_RAW, "", XMPConst.REMOVE_ALL_PROPERTIES);
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
function deleteDocumentAncestorsMetadata() {
whatApp = String(app.name); //String version of the app name
if (whatApp.search("Photoshop") > 0) { //Check for photoshop specifically, or this will cause errors
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
// Begone foul Document Ancestors!
xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
}
}
app.togglePalettes();
app.displayDialogs = restoreDialogMode;
alert('Script completed!' + '\n' + fileList.length + ' source files have created ' + fileCounter + ' layer comps, saved to:' + '\r\r' + outputFolder.fsName);
})();
Copy link to clipboard
Copied
Hi there,
Just tested this out and it worked perfectly. Thank you so much for your help, this will help my workflow immensely!
Copy link to clipboard
Copied
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more