Copy link to clipboard
Copied
Hi, I was wondering if a direction could be given on how I might go about creating a script that would open file "0001.tif" from folder A and file "0001.tif" from folder B and layer the folder B image into folder A image, saves and closes, as well as, keeping a counter so that the script then moves on to check and open image "0002.tif" and so on until it doesn't find any more images. Thoughts? Is it possible?
A long time ago I did Actionscript, which was like Javascript, but most of that knowledge has faded.
Any advice on how to approach this or how to start would be amazing. Thanks!
//community.adobe.com/t5/photoshop/auto-merge-files/m-p/10753387
// Auto merge files
// Reference code:
// https://forums.adobe.com/thread/2116421
// https://forums.adobe.com/message/8597315#8597315
#target photoshop
var folder1 = Folder.selectDialog("Please select the base folder with files to process"); // input folder 1
var folder2 = Folder.selectDialog("Please select the layered folder with files to process"); // input folder 2
var saveFolder = Folder.selectDialog("Please select the fo
...
Copy link to clipboard
Copied
Try the following four scripts, adjustments can be made as required...
Instructions here:
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
/*
Photoshop script to auto stack pair of images, then auto-align, and export.
https://community.adobe.com/t5/photoshop/photoshop-script-to-auto-stack-pair-of-images-then-auto-align-and-export/td-p/11989171
Auto Align Files from 2 Folders to TIFF.jsx
Stephen Marsh
Version 1.4 - 6th May 2021
*/
#target photoshop
(function () {
if (app.documents.length === 0) {
// Save the current dialog display settings
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
// Input folder 1
var folder1 = Folder.selectDialog("Please select the originals folder");
if (folder1 === null) return;
// Input folder 2
var folder2 = Folder.selectDialog("Please select the processed files folder");
if (folder2 === null) return;
// Validate input folder selection
var validateInputDir = (folder1.fsName === folder2.fsName);
if (validateInputDir === true) {
alert("Script cancelled as both the input folders are the same");
return;
}
var searchMask = '*.???';
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
// Alpha-numeric sort
list1.sort();
list2.sort();
// Validate that folder 1 & 2 lists are not empty
var validateEmptyList = (list1.length > 0 && list2.length > 0);
if (validateEmptyList === false) {
alert("Script cancelled as one of the input folders is empty");
return;
}
// Validate that the item count in folder 1 & 2 matches
var validateListLength = (list1.length === list2.length);
if (validateListLength === false) {
alert("Script cancelled as the input folders don't have equal quantities of images");
return;
}
// Output folder
var saveFolder = Folder.selectDialog("Please select the folder to save to");
if (saveFolder === null) return;
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
var docName = doc.name.replace(/\.[^\.]+$/, '');
backgroundLayerNameToVariableName(docName, 100, 2);
placeFile(list2[i], 100);
app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
// Action set to run
var actionSet = "AUTO-ALIGN-SET2";
// Action to run from set
var actionName = "AUTO_ALIGN2";
// Run it!
app.doAction(actionName, actionSet);
tiffSaveOptions = new TiffSaveOptions();
tiffSaveOptions.embedColorProfile = true;
tiffSaveOptions.byteOrder = ByteOrder.IBM;
tiffSaveOptions.transparency = true;
tiffSaveOptions.layers = false;
tiffSaveOptions.layerCompression = LayerCompression.ZIP;
tiffSaveOptions.interleaveChannels = true;
tiffSaveOptions.alphaChannels = true;
tiffSaveOptions.annotations = true;
tiffSaveOptions.spotColors = true;
tiffSaveOptions.saveImagePyramid = false;
tiffSaveOptions.imageCompression = TIFFEncoding.NONE;
doc.saveAs(new File(saveFolder + '/' + docName + '.tif'), tiffSaveOptions);
doc.close(SaveOptions.DONOTSAVECHANGES);
}
alert('Script completed!' + '\n' + 'Files saved to:' + '\r' + saveFolder.fsName);
// Restore the dialogs
app.displayDialogs = savedDisplayDialogs;
// Here be functions
function placeFile(file, scale) {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
}
function backgroundLayerNameToVariableName(layerName, opacity, layerID) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var reference = new ActionReference();
reference.putProperty(s2t("layer"), s2t("background"));
descriptor.putReference(c2t("null"), reference);
descriptor2.putString(s2t("name"), layerName);
descriptor2.putUnitDouble(s2t("opacity"), s2t("percentUnit"), opacity);
descriptor2.putEnumerated(s2t("mode"), s2t("blendMode"), s2t("normal"));
descriptor.putObject(s2t("to"), s2t("layer"), descriptor2);
descriptor.putInteger(s2t("layerID"), layerID);
executeAction(s2t("set"), descriptor, DialogModes.NO);
}
}
else {
alert('Please close all open documents before running this script!');
}
}());
Copy link to clipboard
Copied
Wrong code posted!
Copy link to clipboard
Copied
// combine images from two folders;
// 2016, use it at your own risk;
#target photoshop
// select folders;
var theFolder1 = Folder.selectDialog("select folder");
if (theFolder1) {
var theFolder2 = Folder.selectDialog("select other folder");
if (theFolder2 && String(theFolder1) != String(theFolder2)) {
// get files;
var theFiles1 = theFolder1.getFiles(/\.(jpg|tif|eps|psd)$/i);
var theFiles2 = theFolder2.getFiles(/\.(jpg|tif|eps|psd)$/i);
// if more than one image is in the folder and equal number in both;
if (theFiles1.length > 0 && theFiles2.length == theFiles1.length) {
// tif options;
tifOpts = new TiffSaveOptions();
tifOpts.embedColorProfile = true;
tifOpts.imageCompression = TIFFEncoding.TIFFLZW;
tifOpts.alphaChannels = false;
tifOpts.byteOrder = ByteOrder.MACOS;
tifOpts.layers = true;
// do the operation;
for (var m = 0; m < theFiles1.length; m++) {
var theFile = theFiles1[m];
var theOtherFile = theFiles2[m];
// create file;
var myDocument = app.open(File(theFile));
var docName = myDocument.name;
var basename = docName.match(/(.*)\.[^\.]+$/)[1];
var docPath = myDocument.path;
// place the corresponding file;
placeScaleFile(theOtherFile, 0, 0, 100);
//save tif as a copy:
myDocument.saveAs((new File(Folder(theFolder1).parent + "/" + basename + "_combined" + ".tif")), tifOpts, true);
myDocument.close(SaveOptions.DONOTSAVECHANGES)
}
};
alert("done")
}
};
////// get from subfolders //////
function retrieveJPGs(theFolder, theFiles) {
if (!theFiles) { var theFiles = [] };
var theContent = theFolder.getFiles();
for (var n = 0; n < theContent.length; n++) {
var theObject = theContent[n];
if (theObject.constructor.name == "Folder") {
theFiles = retrieveJPGs(theObject, theFiles)
};
if (theObject.name.slice(-4) == ".jpg" || theObject.name.slice(-4) == ".JPG") {
theFiles = theFiles.concat(theObject)
}
};
return theFiles
};
////// place //////
function placeScaleFile(file, xOffset, yOffset, theScale) {
// =======================================================
var idPlc = charIDToTypeID("Plc ");
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc5.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc5.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc6 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc6.putUnitDouble(idHrzn, idPxl, xOffset);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc6.putUnitDouble(idVrtc, idPxl, yOffset);
var idOfst = charIDToTypeID("Ofst");
desc5.putObject(idOfst, idOfst, desc6);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc5.putUnitDouble(idWdth, idPrc, theScale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc5.putUnitDouble(idHght, idPrc, theScale);
var idLnkd = charIDToTypeID("Lnkd");
desc5.putBoolean(idLnkd, false);
executeAction(idPlc, desc5, DialogModes.NO);
return app.activeDocument.activeLayer;
};
Copy link to clipboard
Copied
//community.adobe.com/t5/photoshop/auto-merge-files/m-p/10753387
// Auto merge files
// Reference code:
// https://forums.adobe.com/thread/2116421
// https://forums.adobe.com/message/8597315#8597315
#target photoshop
var folder1 = Folder.selectDialog("Please select the base folder with files to process"); // input folder 1
var folder2 = Folder.selectDialog("Please select the layered folder with files to process"); // input folder 2
var saveFolder = Folder.selectDialog("Please select the folder to save to..."); // output folder
var searchMask = '*.???';
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
list1.sort(); // Alpha-numeric sort
list2.sort(); // Alpha-numeric sort
app.displayDialogs = DialogModes.NO;
var psdOptions = new PhotoshopSaveOptions();
psdOptions.embedColorProfile = true;
psdOptions.alphaChannels = true;
psdOptions.layers = true;
psdOptions.spotColors = true;
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
var docName = doc.name;
placeFile(list2[i], 100);
doc.activeLayer.blendMode = BlendMode.MULTIPLY; //change blend mode
doc.saveAs(new File(saveFolder + '/' + docName.split('.')[0] + '.psd'), psdOptions);
doc.close(SaveOptions.DONOTSAVECHANGES);
};
alert('Script completed!' + '\n' + 'Files saved to:' + '\r' + saveFolder.fsName);
function placeFile(file, scale) {
try {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
}
catch (e) { }
}//end function placeFile
Copy link to clipboard
Copied
Amazing! Thanks for giving me somewhere to start. Will give these a try and see what I can get out of them.
Copy link to clipboard
Copied
What do you want to do once you have one layer stacked over the other?
Some of these scripts run an action. Some use blend modes or opacity of the upper layer over the lower layer.
Where should the combined file be saved, with/without layers, what name etc?
There is a lot to think about.
Copy link to clipboard
Copied
Hi, I simply want to save the file with the layered image, unflattened and it doesn't need to be saved with a new name or in a new folder.
Other coding question, and this may not be the thread to ask, but is there a way to skip a dialog box and have a script run automatically?
I'm using a script to export layers as files, but it pops up with a dialog box for every layered file when I run it in an action. Is there a way to have it skip having to hit the RUN button or is there a way to add an autorun function upon load of dialogbox?
Copy link to clipboard
Copied
![]()
Hi, I simply want to save the file with the layered image, unflattened and it doesn't need to be saved with a new name or in a new folder.
By @jensou
As I said, when it comes to scripting - you need to think about it... There are two separate input folders, so where to save, this is not clear? Input folder A (overwriting), input folder B (overwriting), or somewhere else?
EDIT: Apologies, you did explain in your original post which file should be saved/overwritten.
As the input files are TIFF, do you wish to save layered TIFF or layered PSD?
EDIT: I'll presume layered TIFF.
NOTE: The scripts that I posted don't check/match filenames, they just expect/presume that the files in each folder are naturally alphabetically sorting and have the same names so that the correct files are just "naturally" paired.
Copy link to clipboard
Copied
@jensou – here is a "final" refined version specifically configured for this topic:
/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-open-files-and-layer-them/m-p/12532657
Script to open files and layer them?
Stephen Marsh, v1.1 - 20th November 2021
Note: It is assumed that the filenames in both folders are the same (or will at least sort as expected).
*/
#target photoshop
(function () {
if (app.documents.length === 0) {
try {
// Input folder 1
var folder1 = Folder.selectDialog("Select the first folder:");
if (folder1 === null) {
alert('Script cancelled!');
return;
}
// Input folder 2
var folder2 = Folder.selectDialog("Select the second folder to layer:");
if (folder2 === null) {
alert('Script cancelled!');
return;
}
// Validate input folder selection
var validateInputDir = (folder1.fsName === folder2.fsName);
if (validateInputDir === true) {
alert("Script cancelled as both the input folders are the same!");
return;
}
// Save folder is the first input folder
var saveFolder = folder1;
// Limit the file input to tiff
var list1 = folder1.getFiles(/\.(tif|tiff)$/i);
var list2 = folder2.getFiles(/\.(tif|tiff)$/i);
// Alpha-numeric sort
list1.sort();
list2.sort();
// Validate that folder 1 & 2 lists are not empty
var validateEmptyList = (list1.length > 0 && list2.length > 0);
if (validateEmptyList === false) {
alert("Script cancelled as one of the input folders is empty!");
return;
}
// Validate that the item count in folder 1 & 2 matches
var validateListLength = (list1.length === list2.length);
if (validateListLength === false) {
alert("Script cancelled as the input folders don't have equal quantities of images!");
return;
}
// Save and set the dialog display settings
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
// TIFF save options
tifOpts = new TiffSaveOptions();
tifOpts.embedColorProfile = true;
tifOpts.imageCompression = TIFFEncoding.TIFFLZW;
tifOpts.alphaChannels = true;
tifOpts.byteOrder = ByteOrder.MACOS;
tifOpts.layers = true;
// Perform the stacking and saving
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
var docName = doc.name;
placeFile(list2[i], 100);
app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
doc.saveAs(new File(saveFolder + '/' + docName), tifOpts);
doc.close(SaveOptions.DONOTSAVECHANGES);
}
function placeFile(file, scale) {
try {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
} catch (e) { }
}
// End of script
app.displayDialogs = savedDisplayDialogs;
app.beep();
var listCount = list1.length;
alert('Script completed!' + '\n' + listCount + ' layered TIFF files saved to:' + '\r' + saveFolder.fsName);
} catch (err) {
alert("An unexpected error has occurred!");
}
} else {
alert('Please close all open documents before running this script!');
}
}());
Copy link to clipboard
Copied
That worked insanely perfectly! I was not even close to being on the right track changing the previous code to work like this does. Thanks so much.
Copy link to clipboard
Copied
This updated generic script adds a single unified user interface window.
v1.0 Features:
* Select the 1st input folder (lower layer)
* Select the 2nd input folder (upper layer)
* Select the output folder
* Supported input formats: PNG, JPG, TIFF, PSD, PSB, WEBP (the underlying code is easily changed to add more formats)
* Files will be stacked in alpha/numeric sort order from each input folder
* Supported output formats: PSD, TIFF (layers or flattened) or JPG (flattened), PNG or WEBP.
* Option to Remove all supported XMP metadata
* Dropdown menus to select a loaded action set and action to play on the top layer of each set (the action can then select other layers as needed for additional processing)
What it doesn't do: The script doesn't attempt to auto-align the stacked paired documents. All images must have the same pixel dimensions and resolution PPI values.
/*
Stack Documents from 2 Folders to Sets of 2 Layers scriptUI GUI.jsx
Stephen Marsh
v1.0 - 17th October 2024
v1.1 - 15th November 2024, WebP save format support added
v1.2 - 17th November 2024, Added "user friendly" file format variables for save options for PSD, TIFF, JPEG, PNG and WEBP formats
v1.3 - 29th January 2025, Added PSB Large Document Format save option
v1.4 - 30th January 2025, Added a dropdown menu to select different file naming options
v1.5 - 30th April 2025, Added an option to the renaming dropdown to use the combined layer names to name the files (in reverse order)
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-open-files-and-layer-them/m-p/12532657
Note: It is expected that the filenames in both folders alphabetically sort in the correct order and that all files are the same pixel dimensions and resolution/PPI value.
Related topics:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/need-help-to-create-script-that-stacks-files-with-the-same-names-together/m-p/13688339
https://community.adobe.com/t5/photoshop-ecosystem-discussions/auto-merge-files/m-p/10753387
https://community.adobe.com/t5/Photoshop/Combine-two-psd-into-one-Keep-filename/td-p/10610400
https://community.adobe.com/t5/photoshop/auto-merge-files/m-p/10753387
https://community.adobe.com/t5/photoshop-ecosystem-discussions/batch-script/td-p/12700356
https://community.adobe.com/t5/photoshop-ecosystem-discussions/png-and-jpeg-clipping-mask/m-p/12730278
https://community.adobe.com/t5/photoshop-ecosystem-discussions/is-there-a-script-to-apply-a-series-of-alpha-channels-in-bulk-to-a-series-of-images/td-p/13642975
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-or-batch-tutorial-on-how-to-copy-alpha-channel-from-one-set-of-images-to-another/td-p/14205993
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-automate-load-files-into-stack/m-p/13499068
https://community.adobe.com/t5/photoshop-ecosystem-discussions/batch-merge-load-images-from-2-directories-as-layers/td-p/12804714
*/
#target photoshop;
// Adjust the following "user friendly" variables as required. A GUI for these file format options isn't planned!
// savePSD global variables
var embedColorProfile = true; // Boolean: true | false
var alphaChannels = true; // Boolean: true | false
var annotations = true; // Boolean: true | false
var spotColors = true; // Boolean: true | false
// saveTIFF global variables
var tiffEmbedColorProfile = true; // Boolean: true | false
var tiffByteOrder = ByteOrder.IBM; // ByteOrder.MACOS | ByteOrder.IBM
var tiffTransparency = true; // Boolean: true | false
var tiffLayerCompression = LayerCompression.ZIP; // LayerCompression.RLE | LayerCompression.ZIP
var tiffInterleaveChannels = true; // Boolean: true | false
var tiffAlphaChannels = true; // Boolean: true | false
var tiffAnnotations = true; // Boolean: true | false
var tiffSpotColors = true; // Boolean: true | false
var tiffSaveImagePyramid = false; // Boolean: true | false
var tiffImageCompression = TIFFEncoding.TIFFLZW; // NONE | JPEG | TIFFLZW | TIFFZIP
// saveJPEG global variables
var jpegEmbedColorProfile = true; // Boolean: true | false
var jpegFormatOptions = FormatOptions.STANDARDBASELINE; // FormatOptions.STANDARDBASELINE | FormatOptions.OPTIMIZEDBASELINE | FormatOptions.PROGRESSIVE
var jpegMatte = MatteType.NONE; // MatteType.NONE | MatteType.WHITE | MatteType.BLACK
var jpegQuality = 10; // Numeric: 0 - 12
// savePNG global variables
var pngCompression = 0; // Numeric: 0 - 9
var pngInterlaced = false; // Boolean: true | false
// saveWebP global variables
var webPCompressionType = "compressionLossy"; // String: "compressionLossless" | "compressionLossy"
var webPCompIsLossless = false; // Boolean: true | false
var webPQuality = 75; // Numeric: 0 (lowest lossy quality) - 100 (highest lossy quality)
var webPIncludeXMPData = true; // Boolean: true | false
var webPIncludeEXIFData = false; // Boolean: true | false
var webPIncludePsExtras = false; // Boolean: true | false
var webPLowerCase = true; // Boolean: true | false
var webPEmbedProfiles = true; // Boolean: true | false
// Folder button global variables, declare them early for the main dialog window OK button!
var folder1Btn, folder1, folder2Btn, folder2, saveFolderBtn;
(function () {
if (app.documents.length === 0) {
try {
// Create the main dialog
var dlg = new Window("dialog", "Stack Documents from 2 Folders to Sets of 2 Layers (v1.5)");
dlg.orientation = "column";
dlg.alignChildren = "fill";
// Input folder panel
var inputPanel = dlg.add("panel", undefined, "Input Folders");
inputPanel.orientation = "column";
inputPanel.alignChildren = "fill";
// Input folder 1
var folder1Group = inputPanel.add("group");
folder1Group.orientation = "row";
folder1Group.alignChildren = "fill";
var folder1Btn = folder1Group.add("button", undefined, "Select Input Folder 1");
folder1Btn.helpTip = "Select the folder for the bottom layer";
var folder1Path = folder1Group.add("statictext", undefined, "No folder selected", { truncate: "middle" });
folder1Path.size = [427, 25];
folder1Btn.onClick = function () {
var folder1 = Folder.selectDialog("Select the 1st folder:");
if (folder1 !== null) folder1Path.text = folder1.fsName;
};
// Input folder 2
var folder2Group = inputPanel.add("group");
folder2Group.orientation = "row";
folder2Group.alignChildren = "fill";
var folder2Btn = folder2Group.add("button", undefined, "Select Input Folder 2");
folder2Btn.helpTip = "Select the folder for the top layer";
var folder2Path = folder2Group.add("statictext", undefined, "No folder selected", { truncate: "middle" });
folder2Path.size = [427, 25];
folder2Btn.onClick = function () {
var folder2 = Folder.selectDialog("Select the 2nd folder to layer:");
if (folder2 !== null) folder2Path.text = folder2.fsName;
};
// Save folder panel
var savePanel = dlg.add("panel", undefined, "Output Folder");
savePanel.orientation = "column";
savePanel.alignChildren = "left";
// Save folder
var saveFolderGroup = savePanel.add("group");
saveFolderGroup.orientation = "row";
saveFolderGroup.alignChildren = "fill";
var saveFolderBtn = saveFolderGroup.add("button", undefined, "Select Output Folder");
saveFolderBtn.helpTip = "Select the folder to save to";
var saveFolderPath = saveFolderGroup.add("statictext", undefined, "No folder selected", { truncate: "middle" });
saveFolderPath.size = [427, 25];
saveFolderBtn.onClick = function () {
var saveFolder = Folder.selectDialog("Select the folder to save to:");
if (saveFolder !== null) saveFolderPath.text = saveFolder.fsName;
};
// Settings folder panel
var settingsPanel = dlg.add("panel", undefined, "Settings");
settingsPanel.orientation = "column";
settingsPanel.alignChildren = "left";
// Create conditional dropdown options array based on Photoshop version 2022 check/test
var formatOptions = ["PSD", "PSB", "TIFF", "JPEG", "PNG"];
if (parseFloat(app.version) >= 23) {
formatOptions.push("WEBP");
}
// Populate the dropdown menu with format options
var settingsFormatDropdown = settingsPanel.add("dropdownlist", undefined, formatOptions);
settingsFormatDropdown.selection = 0; // Default to PSD
settingsFormatDropdown.preferredSize.width = 168;
// Add checkbox for saving layers
var settingsLayersCheckbox = settingsPanel.add("checkbox", undefined, "Layers");
settingsLayersCheckbox.value = true; // Default to true
// Function to update checkbox state based on selected format
function updateSettingsCheckboxState() {
var selectedFormat = settingsFormatDropdown.selection.text;
var layeredFormat = (selectedFormat === "PSD" || selectedFormat === "PSB" || selectedFormat === "TIFF");
settingsLayersCheckbox.enabled = layeredFormat;
settingsLayersCheckbox.value = layeredFormat;
}
// Set initial checkbox state
updateSettingsCheckboxState();
// Add onChange event listener to settingsFormatDropdown
settingsFormatDropdown.onChange = function () {
updateSettingsCheckboxState();
};
// Add checkbox for removing XMP metadata
var removeSettingsXMPCheckbox = settingsPanel.add("checkbox", undefined, "Remove XMP Metadata");
removeSettingsXMPCheckbox.value = true;
removeSettingsXMPCheckbox.helpTip = "Remove XMP metadata, including photoshop:DocumentAncestors metadata bloat!";
// Add a dropdown menu for save naming options
settingsPanel.add('statictext', undefined, 'Select a File Naming Option:');
var namingDropdown = settingsPanel.add('dropdownlist', undefined, [
'Use the top layer to name the files',
'Use the bottom layer to name the files',
'Use the combined layer names to name the files',
'Use the combined layer names to name the files (reversed)',
]);
namingDropdown.selection = 0; // Default selection
// Run Action panel
var actionsPanel = dlg.add("panel", undefined, "Run Action on top layer");
actionsPanel.orientation = "column";
actionsPanel.alignChildren = "fill";
// Add action menus to the actions panel
var actionGroup = actionsPanel.add("group");
actionGroup.orientation = "column";
actionGroup.alignChildren = ["fill", "top"];
actionGroup.alignment = ["fill", "top"];
var actionSetGroup = actionGroup.add("group");
actionSetGroup.orientation = "row";
actionSetGroup.alignChildren = ["left", "center"];
actionSetGroup.alignment = ["fill", "top"];
actionSetGroup.add('statictext', undefined, 'Action Set:').preferredSize.width = 70;
var actionSetDropdown = actionSetGroup.add('dropdownlist', undefined, []);
actionSetDropdown.alignment = ["fill", "center"];
var actionLabelGroup = actionGroup.add("group");
actionLabelGroup.orientation = "row";
actionLabelGroup.alignChildren = ["left", "center"];
actionLabelGroup.alignment = ["fill", "top"];
actionLabelGroup.add('statictext', undefined, 'Action:').preferredSize.width = 70;
var actionDropdown = actionLabelGroup.add('dropdownlist', undefined, []);
actionDropdown.alignment = ["fill", "center"];
// Populate the action set dropdown
actionSetDropdown.add('item', '');
var actionSets = getActionSets();
for (var i = 0; i < actionSets.length; i++) {
actionSetDropdown.add('item', actionSets[i]);
}
actionSetDropdown.selection = actionSetDropdown.items[0];
actionDropdown.add('item', '');
// When the action set is changed, update the action dropdown
actionSetDropdown.onChange = function () {
actionDropdown.removeAll();
if (actionSetDropdown.selection && actionSetDropdown.selection.text != '') {
var actions = getActions(actionSetDropdown.selection.text);
for (var i = 0; i < actions.length; i++) {
actionDropdown.add('item', actions[i]);
}
if (actions.length > 0) {
actionDropdown.selection = actionDropdown.items[0];
}
} else {
actionDropdown.add('item', '');
actionDropdown.selection = actionDropdown.items[0];
}
};
// OK and Cancel buttons
var buttonGroup = dlg.add("group");
buttonGroup.alignment = "right";
var cancelBtn = buttonGroup.add("button", undefined, "Cancel");
var okBtn = buttonGroup.add("button", undefined, "OK");
okBtn.onClick = function () {
// Validation check for folder1
if (folder1Path.text === "No folder selected") {
alert("Please select the first input folder!");
return;
}
// Validation check for folder2
if (folder2Path.text === "No folder selected") {
alert("Please select the second input folder!");
return;
}
// Validation check for save folder
if (saveFolderPath.text === "No folder selected") {
alert("Please select the output folder!");
return;
}
// Validate that the two input folders are not the same
if (folder1Path.text === folder2Path.text) {
alert("Both input folders cannot be the same! Please select different folders.");
return;
}
// Validate that the output folder is not the same as either input folder
if (saveFolderPath.text === folder1Path.text || saveFolderPath.text === folder2Path.text) {
alert("The output folder cannot be the same as either input folder! Please select a different output folder.");
return;
}
// Validate that folder 1 & 2 lists are not empty
if (list1.length > 0 && list2.length > 0) {
alert("Script cancelled as one of the input folders is empty!");
return;
}
// Validate that the item count in folder 1 & 2 matches
if (list1.length === list2.length) {
alert("Script cancelled as the input folders don't have equal quantities of images!");
return;
}
dlg.close(1);
};
// Show the dialog
if (dlg.show() === 1) {
var folder1 = new Folder(folder1Path.text);
var folder2 = new Folder(folder2Path.text);
var saveFolder = new Folder(saveFolderPath.text);
var list1 = folder1.getFiles(/\.(tif|tiff|psd|jpg|jpeg|png|webp)$/i);
var list2 = folder2.getFiles(/\.(tif|tiff|psd|jpg|jpeg|png|webp)$/i);
list1.sort();
list2.sort();
var savedDisplayDialogs = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
// Hide the Photoshop panels
app.togglePalettes();
// Create the progress window
var progress = new Window("palette");
progress.text = "Processing Files";
progress.orientaton = "column";
progress.alignChildren = ["center", "top"];
progress.spacing = 10;
progress.margins = 16;
var progressBar = progress.add("progressbar", undefined, 0, list1.length);
progressBar.preferredSize.width = 300;
var progressText = progress.add("statictext", undefined, "Processing...");
progress.show();
// Set the file progress counter
var fileCounter = 0;
// Stack the docs as layer pairs
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
docNameToLayerName();
placeFile(list2[i], 100);
try {
// Reset the SO transform to account for differing PPI values
executeAction(stringIDToTypeID("placedLayerResetTransforms"), undefined, DialogModes.NO);
// Centre the SO layer on the canvas
app.activeDocument.activeLayer.translate(app.activeDocument.width / 2 - (app.activeDocument.activeLayer.bounds[0] + app.activeDocument.activeLayer.bounds[2]) / 2,
app.activeDocument.height / 2 - (app.activeDocument.activeLayer.bounds[1] + app.activeDocument.activeLayer.bounds[3]) / 2);
// Rasterize the SO
app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
} catch (err) {
alert("Error!" + "\r" + err + "\r" + 'Line: ' + err.line);
}
// Run the selected action on the top layer
if (actionSetDropdown.selection && actionSetDropdown.selection.text != '' &&
actionDropdown.selection && actionDropdown.selection.text != '') {
selectFrontLayer();
runAction(actionSetDropdown.selection.text, actionDropdown.selection.text);
}
// Remove XMP metadata if checkbox is checked
if (removeSettingsXMPCheckbox.value) {
removeXMP();
}
// File saving options for user dropdown menu selection
var saveFile;
var combinedLayerNames = '';
var combinedLayerNamesReversed = '';
var layers = app.activeDocument.layers;
// Combine layer names (for option 3)
for (var j = 0; j < layers.length; j++) {
combinedLayerNames += layers[j].name;
if (j < layers.length - 1) combinedLayerNames += '_'; // Separate names with an underscore
}
// Combine layer names (for option 4)
for (var k = layers.length - 1; k >= 0; k--) {
combinedLayerNamesReversed += layers[k].name;
if (k > 0) combinedLayerNamesReversed += '_'; // Separate names with an underscore
}
// Determine file naming option based on user dropdown menu selection
switch (namingDropdown.selection.index) {
case 0:
saveFile = new File(saveFolder + '/' + layers[0].name); // Top layer name (option 1)
break;
case 1:
saveFile = new File(saveFolder + '/' + layers[layers.length - 1].name); // Bottom layer name (option 2)
break;
case 2:
saveFile = new File(saveFolder + '/' + combinedLayerNames); // Combined layer names (option 3)
break;
case 3:
saveFile = new File(saveFolder + '/' + combinedLayerNamesReversed); // Combined layer names (option 4)
break;
}
// Save with selected format
switch (settingsFormatDropdown.selection.text) {
case "PSD":
savePSD(saveFile, settingsLayersCheckbox.value);
break;
case "PSB":
savePSB(saveFile, settingsLayersCheckbox.value);
break;
case "TIFF":
saveTIFF(saveFile, settingsLayersCheckbox.value);
break;
case "JPEG":
saveJPEG(saveFile);
break;
case "PNG":
savePNG(saveFile);
break;
case "WEBP":
saveWebP(saveFile);
break;
}
doc.close(SaveOptions.DONOTSAVECHANGES);
// Update progress
fileCounter++;
progressBar.value = fileCounter;
progressText.text = "Processing...";
progress.update();
}
// Clean up, close the progress window and restore the Photoshop panels
// Ensure Photoshop has focus before closing the progress window
app.bringToFront();
progress.close();
app.displayDialogs = savedDisplayDialogs;
app.beep();
var listCount = list1.length;
alert('Script completed!' + '\n' + listCount + ' ' + settingsFormatDropdown.selection.text + ' files saved to:' + '\r' + saveFolder.fsName);
// Restore the Photoshop panels
app.togglePalettes();
} else {
//alert('Script cancelled!');
}
} catch (err) {
alert("Error!" + "\r" + err + "\r" + 'Line: ' + err.line);
}
} else {
alert('Please close all open documents before running this script!');
}
})();
// Functions
function docNameToLayerName() {
var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
app.activeDocument.activeLayer.name = layerName;
}
function removeXMP() {
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 selectFrontLayer() {
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Frnt"));
desc1.putReference(charIDToTypeID("null"), ref1);
executeAction(charIDToTypeID("slct"), desc1, DialogModes.NO);
}
function placeFile(file, scale) {
try {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
} catch (err) {
alert("Error!" + "\r" + err + "\r" + 'Line: ' + err.line);
}
}
function savePSD(saveFile, saveLayers) {
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
psdSaveOptions.layers = saveLayers;
psdSaveOptions.annotations = true;
psdSaveOptions.spotColors = true;
app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
}
function savePSB(saveFile, saveLayers) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putBoolean(s2t("maximizeCompatibility"), true);
descriptor.putObject(s2t("as"), s2t("largeDocumentFormat"), descriptor2);
descriptor.putPath(s2t("in"), saveFile);
descriptor.putBoolean(s2t("lowerCase"), true);
descriptor.putBoolean(s2t("layers"), saveLayers);
executeAction(s2t("save"), descriptor, DialogModes.NO);
}
function saveTIFF(saveFile, saveLayers) {
tiffSaveOptions = new TiffSaveOptions();
tiffSaveOptions.embedColorProfile = true;
tiffSaveOptions.byteOrder = ByteOrder.IBM;
tiffSaveOptions.transparency = true;
tiffSaveOptions.layers = saveLayers;
tiffSaveOptions.layerCompression = LayerCompression.ZIP;
tiffSaveOptions.interleaveChannels = true;
tiffSaveOptions.alphaChannels = true;
tiffSaveOptions.annotations = true;
tiffSaveOptions.spotColors = true;
tiffSaveOptions.saveImagePyramid = false;
tiffSaveOptions.imageCompression = TIFFEncoding.TIFFLZW;
app.activeDocument.saveAs(saveFile, tiffSaveOptions, true, Extension.LOWERCASE);
}
function saveJPEG(saveFile) {
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 10;
activeDocument.saveAs(saveFile, jpgSaveOptions, true, Extension.LOWERCASE);
}
function savePNG(saveFile) {
var pngOptions = new PNGSaveOptions();
pngOptions.compression = 0;
pngOptions.interlaced = false;
app.activeDocument.saveAs(saveFile, pngOptions, true, Extension.LOWERCASE);
}
function saveWebP(saveFile) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t("compressionLossy")); // Compression string = "compressionLossless" || "compressionLossy"
var WebPCompIsLossless = false; // set the default flag for compression
if (WebPCompIsLossless == false) {
// 0 (lowest lossy quality) - 100 (highest lossy quality)
descriptor2.putInteger(s2t("quality"), 75); // number variable
}
// Metadata options
descriptor2.putBoolean(s2t("includeXMPData"), true); // boolean variable, true or false
descriptor2.putBoolean(s2t("includeEXIFData"), false); // boolean variable, true or false
descriptor2.putBoolean(s2t("includePsExtras"), false); // boolean variable, true or false
// WebP format and save path
descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
descriptor.putPath(s2t("in"), saveFile);
// The extension
descriptor.putBoolean(s2t("lowerCase"), true);
// Embed color profile
descriptor.putBoolean(s2t("embedProfiles"), true);
// Execute the save
executeAction(s2t("save"), descriptor, DialogModes.NO);
}
function getActionSets() {
var actionSets = [];
var i = 1;
while (true) {
try {
var ref = new ActionReference();
ref.putIndex(charIDToTypeID('ASet'), i);
var desc = executeActionGet(ref);
var name = desc.getString(charIDToTypeID('Nm '));
actionSets.push(name);
i++;
} catch (err) {
//alert("Error!" + "\r" + err + "\r" + 'Line: ' + err.line);
break;
}
}
return actionSets;
}
function getActions(actionSet) {
var actions = [];
var i = 1;
while (true) {
try {
var ref = new ActionReference();
ref.putIndex(charIDToTypeID('Actn'), i);
ref.putName(charIDToTypeID('ASet'), actionSet);
var desc = executeActionGet(ref);
var actionName = desc.getString(charIDToTypeID('Nm '));
actions.push(actionName);
i++;
} catch (err) {
//alert("Error!" + "\r" + err + "\r" + 'Line: ' + err.line);
break;
}
}
return actions;
}
function runAction(actionSet, actionName) {
var actionRef = new ActionReference();
actionRef.putName(charIDToTypeID('Actn'), actionName);
actionRef.putName(charIDToTypeID('ASet'), actionSet);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID('null'), actionRef);
executeAction(charIDToTypeID('Ply '), desc, DialogModes.NO);
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Find more inspiration, events, and resources on the new Adobe Community
Explore Now