Skip to main content
Participant
March 28, 2022
Question

Images to layers - large volumes

  • March 28, 2022
  • 3 replies
  • 504 views

The problem:
I have one folder with 10000+ images
Now I want to create layer stacks of all images with a limit of 100 images per stack.
Is there a way to automat this process? 

This topic has been closed for replies.

3 replies

Stephen Marsh
Community Expert
Community Expert
March 30, 2022

@realistic_kid15A7 – so how did the script work for you? 10K is a lot, Photoshop is not great with such large volumes of images, so you will likely need to break this up into smaller batches.

Participant
March 30, 2022

@Stephen Marsh yeah it works. But with some error messages and sometimes Photoshop just quits.
For now I don't understead why, maybe some problems with the some files, ....
Breaking them up in small batches works. 
If I can find a reason why there are some errors, ... I let you know.
Thanks alot for the help, its save me many many hours

 

Kukurykus
Legend
March 30, 2022

Mark the answer as correct solution if it's that you needed 😉

Stephen Marsh
Community Expert
Community Expert
March 28, 2022

I have a "standard" script to do this, as it regularly comes up on the forum...

 

Please read the comments at the head of the script for further info.

 

/* 

Stack N Number of Docs to Layers.jsx
Stephen Marsh
20th August 2021 Version

A generic, skeleton "framework" script to help fast-track development of similar scripts for combining multiple
"sequence" single-layer files to layers.

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 the stack quantity.

A named action set and action can be set on line 137 to "do something" with the stacked layers.

*/

#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();

            //////////////////////////// Static Set Quantity - No GUI ////////////////////////////
            var setQty = 100;
            //////////////////////////////////////////////////////////////////////////////////////

            // or...

            /*
            //////////////////////////// Variable Set Quantity - GUI /////////////////////////////
            // Loop the input prompt until a number is entered
            var origInput;
            while (isNaN(origInput = prompt('No. of files per set (minimum 2):', '2')));
            // Test if cancel returns null, then terminate the script
            if (origInput === null) {
                alert('Script cancelled!');
                return
            }
            // Test if an empty string is returned, then terminate the script 
            if (origInput === '') {
                alert('A value was not entered, script cancelled!');
                return
            }
            // Test if a value less than 2 is returned, then terminate the script 
            if (origInput < 2) {
                alert('A value less than 2 was entered, script cancelled!');
                return
            }
            // Convert decimal input to integer
            var setQty = parseInt(origInput);
            //////////////////////////////////////////////////////////////////////////////////////
            */

            // 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;
            }

            // or

            /*
            // Create the output sub-directory
            var outputFolder = Folder(decodeURI(inputFolder + '/Output Sets Folder'));
            if (!outputFolder.exists) outputFolder.create();
            */

            // 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];

                    // Do something to the stacked active layer (blend mode, opacity etc)
                    // app.activeDocument.activeLayer.blendMode = BlendMode.MULTIPLY;

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

                ////////////////////////////////// Start doing stuff //////////////////////////////////

                // app.doAction("My Action", "My Action Set Folder");

                /*
                // Average stacked layers
                app.runMenuItem(stringIDToTypeID("selectAllLayers"));
                var idnewPlacedLayer = stringIDToTypeID("newPlacedLayer");
                executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
                var idapplyImageStackPluginRenderer = stringIDToTypeID("applyImageStackPluginRenderer");
                var desc1217 = new ActionDescriptor();
                var idimageStackPlugin = stringIDToTypeID("imageStackPlugin");
                var idavrg = charIDToTypeID("avrg");
                desc1217.putClass(idimageStackPlugin, idavrg);
                var idname = stringIDToTypeID("name");
                desc1217.putString(idname, """Mean""");
                executeAction(idapplyImageStackPluginRenderer, desc1217, DialogModes.NO);
                */

                ////////////////////////////////// Finish doing stuff //////////////////////////////////

                // 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');
                // var saveFile = File(outputFolder + '/' + Name + '_x' + setQty + '-Sets' + '.jpg');

                // Call the save function
                savePSD(saveFile);
                //saveTIFF(saveFile);
                //saveJPEG(saveFile);
                //savePNG(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);
                }

                /* Not currently used, a placeholder to swap in/out as needed
                function saveTIFF(saveFile) {
                    tiffSaveOptions = new TiffSaveOptions();
                    tiffSaveOptions.embedColorProfile = true;
                    tiffSaveOptions.byteOrder = ByteOrder.IBM;
                    tiffSaveOptions.transparency = true;
                    // Change layers to false to save without layers
                    tiffSaveOptions.layers = true;
                    tiffSaveOptions.layerCompression = LayerCompression.ZIP;
                    tiffSaveOptions.interleaveChannels = true;
                    tiffSaveOptions.alphaChannels = true;
                    tiffSaveOptions.annotations = true;
                    tiffSaveOptions.spotColors = true;
                    tiffSaveOptions.saveImagePyramid = false;
                    // Image compression = NONE | JPEG | TIFFLZW | TIFFZIP
                    tiffSaveOptions.imageCompression = TIFFEncoding.TIFFLZW;
                    // Save as
                    app.activeDocument.saveAs(saveFile, tiffSaveOptions, true, Extension.LOWERCASE);
                }
                */

                /* Not currently used, a placeholder to swap in/out as needed
                function saveJPEG(saveFile) {
                    jpgSaveOptions = new JPEGSaveOptions();
                    jpgSaveOptions.embedColorProfile = true;
                    jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
                    jpgSaveOptions.matte = MatteType.NONE;
                    jpgSaveOptions.quality = 10;
                    // Save as
                    activeDocument.saveAs(saveFile, jpgSaveOptions, true, Extension.LOWERCASE);
                }
                */

                /* Not currently used, a placeholder to swap in/out as needed
                function savePNG(saveFile) {
                    var pngOptions = new PNGSaveOptions();
                    pngOptions.compression = 0; // 0-9
                    pngOptions.interlaced = false;
                    // Save as
                    app.activeDocument.saveAs(saveFile, pngOptions, 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();

            // Ensure that the following file format filter matches the save format
            // .getFiles(/\.(tif|tiff)$/i);
            var outputList = outputFolder.getFiles(/\.(psd)$/i);
            // var outputList = outputFolder.getFiles(/\.(jpg|jpeg)$/i);
            alert('Script completed!' + '\n' + outputList.length + ' 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 "N" Number of Sets:' + '\n' + 'Please close all open documents before running this script!');

}

 

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

c.pfaffenbichler
Community Expert
Community Expert
March 28, 2022

And it even beeps! 

Stephen Marsh
Community Expert
Community Expert
March 28, 2022

@c.pfaffenbichler wrote:

And it even beeps! 


 

I'd prefer it if it quacked, but I settle for a beep!

 

Not sure what happens on Windows, but on Mac I like it how everything flashes if the volume is set to zero.

c.pfaffenbichler
Community Expert
Community Expert
March 28, 2022

This should be »easily« do-able with Scripting. 

How familiar are you with JavaScript and Photoshop’s DOM?