Skip to main content
Participating Frequently
April 26, 2022
Answered

Photoshop script for image stacking

  • April 26, 2022
  • 1 reply
  • 1249 views

Hi there

I am seeking a solution to streamline part of my work flow. I want to be able to automate the following steps but am unsure how to get there:

1. Load files into stack - load a bunch of photos into a photoshop file, pretty simple - I would do this manually.

Hoping to script this part:

2. Select the first and second layer and duplicate them into a new photoshop file.

3. Repeat step 2 for the rest of the images in the original stack.

That's basically it, but when I tried to record an action for this process, the variable amount of photos per photoshoot made it so that the action either didn't run enough times or ran too many times creating many duplicates.

Any ideas?

This topic has been closed for replies.
Correct answer Stephen Marsh

@andrewh85004476 wrote:

Hi Stephen thanks for the reply.

It will always be a multiple of 2 as the images are paired for further editing. 1 flash shot and one non-flash of the same scene.

I don't see why selecting a folder of 10 would not work - in fact it would probably be more efficient that way


 

Try this script:

 

/* 

Stephen Marsh
20th August 2021 Version

This script requires input files from a single folder to be alpha/numeric sorting in order to stack in the correct
set quantity. 

Example: File-01.jpg File-02.jpg etc, FileA1.tif FileA2.tif etc, File1a.tif File1b.tif etc.

A minimum of 2 or more files per stack is required. The quantity of input files must be evenly divisible by 2.

A named action set and action can be set on line 89 to "do something" with the stacked layers, or further code could be added.

*/

#target photoshop

// app.documents.length === 0
if (!app.documents.length) {

    try {

        // Save and disable dialogs
        var restoreDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.NO;

        // Main script function
        (function () {

            // Select the input folder
            var inputFolder = Folder.selectDialog('Please select the folder with files to process');
            if (inputFolder === null) return;

            // Limit the file format input, add or remove as required
            var fileList = inputFolder.getFiles(/\.(png|jpg|jpeg|tif|tiff|psd|psb)$/i);

            // Force alpha-numeric list sort
            // Use .reverse() for the first filename in the merged file
            // Remove .reverse() for the last filename in the merged file
            fileList.sort().reverse();

            var setQty = 2;

            // Validate that the file list is not empty
            var inputCount = fileList.length;
            var cancelScript1 = (inputCount === 0);
            if (cancelScript1 === true) {
                alert('Zero input files found, script cancelled!');
                return;
            }
            // Validate the input count vs. output count - Thanks to Kukurykus for the advice to test using % modulus
            var cancelScript2 = !(inputCount % setQty);
            alert(inputCount + ' input files stacked into sets of ' + setQty + ' will produce ' + inputCount / setQty + ' output files.');
            // Test if false, then terminate the script
            if (cancelScript2 === false) {
                alert('Script cancelled as the quantity of input files are not evenly divisible by the set quantity.');
                return;
            }

            // Select the output folder
            var outputFolder = Folder.selectDialog("Please select the folder to save to");
            if (outputFolder === null) {
                alert('Script cancelled!');
                return;
            }

            // Loop through and open the file sets
            while (fileList.length) {
                // Sets of N quantity files
                for (var a = 0; a < setQty; a++) {
                    try {
                        app.open(fileList.pop());
                    } catch (e) { }
                }

                // Set the base doc layer name
                app.activeDocument = documents[0];
                docNameToLayerName();

                // Stack all open docs to the base doc
                while (app.documents.length > 1) {
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];

                    ////////////////////////////////// Start doing stuff //////////////////////////////////
                    // app.doAction("My Action", "My Action Set Folder");
                    ////////////////////////////////// Finish doing stuff //////////////////////////////////

                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                }

                // Delete XMP metadata to reduce final file size of output files
                removeXMP();

                // Save name + suffix & save path
                var Name = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                var saveFile = File(outputFolder + '/' + Name + '_x' + setQty + '-Sets' + '.psd');

                // Call the save function
                savePSD(saveFile);

                // Close all open files without saving
                while (app.documents.length) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }

                // Functions

                function savePSD(saveFile) {
                    psdSaveOptions = new PhotoshopSaveOptions();
                    psdSaveOptions.embedColorProfile = true;
                    psdSaveOptions.alphaChannels = true;
                    psdSaveOptions.layers = true;
                    psdSaveOptions.annotations = true;
                    psdSaveOptions.spotColors = true;
                    // Save as
                    app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                }

                function docNameToLayerName() {
                    var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    app.activeDocument.activeLayer.name = layerName;
                }

                function removeXMP() {
                    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();
                }

            }

            // Restore saved dialogs
            app.displayDialogs = restoreDialogMode;

            // End of script notification
            app.beep();
            alert('Script completed!' + '\n' + 'Combined files saved to:' + '\n' + outputFolder.fsName);

            // Open the output folder in the Finder or Explorer
            // outputFolder.execute();

        }());

    } catch (e) {

        // Restore saved dialogs
        app.displayDialogs = restoreDialogMode;
        alert("If you see this message, something went wrong!");

    }
}

else {

    alert('Stack Into Sets of 2:' + '\n' + 'Please close all open documents before running this script!');

}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

1 reply

Stephen Marsh
Community Expert
Community Expert
April 26, 2022

Will the layers length always be a multiple of 2?

 

Rather than stacking say 10 files into a single file, then generating another five x2 stack files, would selecting a folder of 10 files and having the script generate five x2 stack files work? Presuming alpha/numeric filename sorting...

Participating Frequently
April 26, 2022

Hi Stephen thanks for the reply.

It will always be a multiple of 2 as the images are paired for further editing. 1 flash shot and one non-flash of the same scene.

I don't see why selecting a folder of 10 would not work - in fact it would probably be more efficient that way

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
April 26, 2022

@andrewh85004476 wrote:

Hi Stephen thanks for the reply.

It will always be a multiple of 2 as the images are paired for further editing. 1 flash shot and one non-flash of the same scene.

I don't see why selecting a folder of 10 would not work - in fact it would probably be more efficient that way


 

Try this script:

 

/* 

Stephen Marsh
20th August 2021 Version

This script requires input files from a single folder to be alpha/numeric sorting in order to stack in the correct
set quantity. 

Example: File-01.jpg File-02.jpg etc, FileA1.tif FileA2.tif etc, File1a.tif File1b.tif etc.

A minimum of 2 or more files per stack is required. The quantity of input files must be evenly divisible by 2.

A named action set and action can be set on line 89 to "do something" with the stacked layers, or further code could be added.

*/

#target photoshop

// app.documents.length === 0
if (!app.documents.length) {

    try {

        // Save and disable dialogs
        var restoreDialogMode = app.displayDialogs;
        app.displayDialogs = DialogModes.NO;

        // Main script function
        (function () {

            // Select the input folder
            var inputFolder = Folder.selectDialog('Please select the folder with files to process');
            if (inputFolder === null) return;

            // Limit the file format input, add or remove as required
            var fileList = inputFolder.getFiles(/\.(png|jpg|jpeg|tif|tiff|psd|psb)$/i);

            // Force alpha-numeric list sort
            // Use .reverse() for the first filename in the merged file
            // Remove .reverse() for the last filename in the merged file
            fileList.sort().reverse();

            var setQty = 2;

            // Validate that the file list is not empty
            var inputCount = fileList.length;
            var cancelScript1 = (inputCount === 0);
            if (cancelScript1 === true) {
                alert('Zero input files found, script cancelled!');
                return;
            }
            // Validate the input count vs. output count - Thanks to Kukurykus for the advice to test using % modulus
            var cancelScript2 = !(inputCount % setQty);
            alert(inputCount + ' input files stacked into sets of ' + setQty + ' will produce ' + inputCount / setQty + ' output files.');
            // Test if false, then terminate the script
            if (cancelScript2 === false) {
                alert('Script cancelled as the quantity of input files are not evenly divisible by the set quantity.');
                return;
            }

            // Select the output folder
            var outputFolder = Folder.selectDialog("Please select the folder to save to");
            if (outputFolder === null) {
                alert('Script cancelled!');
                return;
            }

            // Loop through and open the file sets
            while (fileList.length) {
                // Sets of N quantity files
                for (var a = 0; a < setQty; a++) {
                    try {
                        app.open(fileList.pop());
                    } catch (e) { }
                }

                // Set the base doc layer name
                app.activeDocument = documents[0];
                docNameToLayerName();

                // Stack all open docs to the base doc
                while (app.documents.length > 1) {
                    app.activeDocument = documents[1];
                    docNameToLayerName();
                    app.activeDocument.activeLayer.duplicate(documents[0]);
                    app.activeDocument = documents[0];

                    ////////////////////////////////// Start doing stuff //////////////////////////////////
                    // app.doAction("My Action", "My Action Set Folder");
                    ////////////////////////////////// Finish doing stuff //////////////////////////////////

                    app.documents[1].close(SaveOptions.DONOTSAVECHANGES);
                }

                // Delete XMP metadata to reduce final file size of output files
                removeXMP();

                // Save name + suffix & save path
                var Name = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                var saveFile = File(outputFolder + '/' + Name + '_x' + setQty + '-Sets' + '.psd');

                // Call the save function
                savePSD(saveFile);

                // Close all open files without saving
                while (app.documents.length) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }

                // Functions

                function savePSD(saveFile) {
                    psdSaveOptions = new PhotoshopSaveOptions();
                    psdSaveOptions.embedColorProfile = true;
                    psdSaveOptions.alphaChannels = true;
                    psdSaveOptions.layers = true;
                    psdSaveOptions.annotations = true;
                    psdSaveOptions.spotColors = true;
                    // Save as
                    app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                }

                function docNameToLayerName() {
                    var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    app.activeDocument.activeLayer.name = layerName;
                }

                function removeXMP() {
                    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();
                }

            }

            // Restore saved dialogs
            app.displayDialogs = restoreDialogMode;

            // End of script notification
            app.beep();
            alert('Script completed!' + '\n' + 'Combined files saved to:' + '\n' + outputFolder.fsName);

            // Open the output folder in the Finder or Explorer
            // outputFolder.execute();

        }());

    } catch (e) {

        // Restore saved dialogs
        app.displayDialogs = restoreDialogMode;
        alert("If you see this message, something went wrong!");

    }
}

else {

    alert('Stack Into Sets of 2:' + '\n' + 'Please close all open documents before running this script!');

}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html