Skip to main content
Known Participant
July 16, 2024
Answered

bulk action solution needed

  • July 16, 2024
  • 4 replies
  • 4002 views

Does anyone know a way to bulk stack pairs of photos (raw and edited jpeg) so they can be auto aligned and then blended via opacity change in one? Prefer adobe based platform but don't think it's possible.

Was ideally looking at doing this from LR to PS, but honestly don't care how it's done. Pretty simple but only know how to do this for one pair of photos at a time. 

 

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

@jonathanb67250519 

 

You can try this first draft script. It's mostly there and should only require cosmetic tweaking, such as removing the manual save folder selection step if you want to save the merged files to the TIFF input folder or automatically create a new merged output folder alongside or within the TIFF input folder.

 

Notes:

* Saves a layered TIFF file, change the boolean from true to false to save a flattened TIFF file  [line 71]

* Layer opacity at 40%  [line 108]

* Optional feature to crop to transparency, remove the leading double-forward slash // comments to enable  [line 111]

* Adds a '_Merged' filename suffix to the saved TIFF file, you could change this name or remove the content inside the single quotes ''  [line 112]

 

I'm happy to make other modifications if required.

 

/*
Stack and Blend 2 Input Folder Files to TIFF.jsx
v1.0, 17th July 2024 - Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/bulk-action-solution-needed/td-p/14741490
*/

#target photoshop

    (function () {

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

            try {

                // JPEG Input folder
                var folder1 = Folder.selectDialog("Select the JPEG image folder:");
                if (folder1 === null) {
                    alert('Script cancelled!');
                    return;
                }

                // TIFF Input folder
                var folder2 = Folder.selectDialog("Select the TIFF image folder:");
                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;
                }

                // Limit the file input to jpg/jpeg
                var list1 = folder1.getFiles(/\.(jpg|jpeg)$/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;
                }

                // Output folder
                var saveFolder = Folder.selectDialog("Please select the folder to save to...");

                // Save and set the dialog display settings
                var savedDisplayDialogs = app.displayDialogs;
                app.displayDialogs = DialogModes.NO;

                // TIFF save options
                var tiffSaveOptions = new TiffSaveOptions();
                tiffSaveOptions.imageCompression = TIFFEncoding.NONE; // TIFFLZW | TIFFZIP | JPEG
                tiffSaveOptions.embedColorProfile = true;
                tiffSaveOptions.byteOrder = ByteOrder.IBM;
                tiffSaveOptions.transparency = true;
                tiffSaveOptions.layers = true;
                tiffSaveOptions.layerCompression = LayerCompression.ZIP;
                tiffSaveOptions.interleaveChannels = true;
                tiffSaveOptions.alphaChannels = true;
                tiffSaveOptions.annotations = true;
                tiffSaveOptions.spotColors = true;
                tiffSaveOptions.saveImagePyramid = false;

                // Hide the Photoshop panels
                app.togglePalettes();

                // Script running notification window - courtesy of William Campbell
                /* https://www.marspremedia.com/download?asset=adobe-script-tutorial-11.zip
                   https://youtu.be/JXPeLi6uPv4?si=Qx0OVNLAOzDrYPB4 */
                var working;
                working = new Window("palette");
                working.preferredSize = [300, 80];
                working.add("statictext");
                working.t = working.add("statictext");
                working.add("statictext");
                working.display = function (message) {
                    this.t.text = message || "Script running, please wait...";
                    this.show();
                    app.refresh();
                };
                working.display();

                // Set the file processing counter
                var counter = 0;

                // Perform the stacking and saving
                for (var i = 0; i < list1.length; i++) {
                    var doc = open(list1[i]);
                    var docName = doc.name.replace(/\.[^\.]+$/, '');
                    placeFile(list2[i], 100);
                    resetTransforms();
                    app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
                    app.activeDocument.activeLayer.opacity = 40; // Layer opacity
                    selectAllLayers();
                    autoAlign();
                    cropTransparency(); // Optional crop
                    app.activeDocument.saveAs(new File(saveFolder + '/' + docName + '_Merged' + '.tif'), tiffSaveOptions);
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                    counter++; // Increment the counter
                }

                // Ensure Photoshop has focus before closing the running script notification window
                app.bringToFront();
                working.close();

                // End of script notification
                app.displayDialogs = savedDisplayDialogs;
                app.beep();
                alert('Script completed!' + '\r' + counter + ' merged TIFF files saved to:' + '\r' + saveFolder.fsName);

                // Restore the Photoshop panels
                app.togglePalettes();

            } catch (err) {
                while (app.documents.length > 0) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }
                alert("Error!" + "\r" + err + ' ' + err.line);
            }

        } else {
            alert('Please close all open documents before running this script!');
        }


        ///// Functions /////

        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) { }
        }

        function resetTransforms() {
            try {
                var idplacedLayerResetTransforms = stringIDToTypeID("placedLayerResetTransforms");
                executeAction(idplacedLayerResetTransforms, undefined, DialogModes.NO);
            } catch (e) {
                //alert("Error!" + "\r" + e + ' ' + e.line); // Errors in 2019 version
                app.refresh();
            }
        }

        function selectAllLayers() {
            try {
                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();
                var reference2 = new ActionReference();
                reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(c2t("null"), reference2);
                executeAction(s2t("selectAllLayers"), descriptor, DialogModes.NO);
                // Add the Background layer if it exists
                reference.putProperty(s2t("layer"), s2t("background"));
                descriptor2.putReference(c2t("null"), reference);
                descriptor2.putEnumerated(s2t("selectionModifier"), s2t("selectionModifierType"), s2t("addToSelection"));
                descriptor2.putBoolean(s2t("makeVisible"), false);
                executeAction(s2t("select"), descriptor2, DialogModes.NO);
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

        function autoAlign() {
            try {
                var desc = new ActionDescriptor();
                var ref = new ActionReference();
                ref.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
                desc.putReference(charIDToTypeID('null'), ref);
                desc.putEnumerated(charIDToTypeID('Usng'), charIDToTypeID('ADSt'), stringIDToTypeID('ADSContent'));
                desc.putEnumerated(charIDToTypeID('Aply'), stringIDToTypeID('projection'), charIDToTypeID('Auto'));
                desc.putBoolean(stringIDToTypeID('vignette'), false);
                desc.putBoolean(stringIDToTypeID('radialDistort'), false);
                executeAction(charIDToTypeID('Algn'), desc, DialogModes.NO);
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

        function cropTransparency() {
            try {
                var s2t = function (s) {
                    return app.stringIDToTypeID(s);
                };
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();
                var descriptor3 = new ActionDescriptor();
                var descriptor4 = new ActionDescriptor();
                var descriptor5 = new ActionDescriptor();
                var descriptor6 = new ActionDescriptor();
                var reference = new ActionReference();
                var reference2 = new ActionReference();
                var reference3 = new ActionReference();
                var reference4 = new ActionReference();
                // Dupe layers to temp merged layer
                descriptor.putBoolean(s2t("duplicate"), true);
                executeAction(s2t("mergeLayersNew"), descriptor, DialogModes.NO);
                // Load selection from layer transparency
                reference.putProperty(s2t("channel"), s2t("selection"));
                descriptor2.putReference(s2t("null"), reference);
                reference2.putEnumerated(s2t("channel"), s2t("channel"), s2t("transparencyEnum"));
                descriptor2.putReference(s2t("to"), reference2);
                executeAction(s2t("set"), descriptor2, DialogModes.NO);
                // Enter quick mask mode
                reference3.putProperty(s2t("property"), s2t("quickMask"));
                reference3.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
                descriptor3.putReference(s2t("null"), reference3);
                // Threshold to 255 levels
                executeAction(s2t("set"), descriptor3, DialogModes.NO);
                descriptor4.putInteger(s2t("level"), 255);
                executeAction(s2t("thresholdClassEvent"), descriptor4, DialogModes.NO);
                // Exit quick mask mode
                reference4.putProperty(s2t("property"), s2t("quickMask"));
                reference4.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
                descriptor5.putReference(s2t("null"), reference4);
                // Crop selection
                executeAction(s2t("clearEvent"), descriptor5, DialogModes.NO);
                descriptor6.putBoolean(s2t("delete"), true);
                executeAction(s2t("crop"), descriptor6, DialogModes.NO);
                // Clean up
                app.activeDocument.activeLayer.remove();
                app.activeDocument.selection.deselect();
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

    }());

 

Instructions for saving and use:

 

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

 

4 replies

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
July 16, 2024

@jonathanb67250519 

 

You can try this first draft script. It's mostly there and should only require cosmetic tweaking, such as removing the manual save folder selection step if you want to save the merged files to the TIFF input folder or automatically create a new merged output folder alongside or within the TIFF input folder.

 

Notes:

* Saves a layered TIFF file, change the boolean from true to false to save a flattened TIFF file  [line 71]

* Layer opacity at 40%  [line 108]

* Optional feature to crop to transparency, remove the leading double-forward slash // comments to enable  [line 111]

* Adds a '_Merged' filename suffix to the saved TIFF file, you could change this name or remove the content inside the single quotes ''  [line 112]

 

I'm happy to make other modifications if required.

 

/*
Stack and Blend 2 Input Folder Files to TIFF.jsx
v1.0, 17th July 2024 - Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/bulk-action-solution-needed/td-p/14741490
*/

#target photoshop

    (function () {

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

            try {

                // JPEG Input folder
                var folder1 = Folder.selectDialog("Select the JPEG image folder:");
                if (folder1 === null) {
                    alert('Script cancelled!');
                    return;
                }

                // TIFF Input folder
                var folder2 = Folder.selectDialog("Select the TIFF image folder:");
                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;
                }

                // Limit the file input to jpg/jpeg
                var list1 = folder1.getFiles(/\.(jpg|jpeg)$/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;
                }

                // Output folder
                var saveFolder = Folder.selectDialog("Please select the folder to save to...");

                // Save and set the dialog display settings
                var savedDisplayDialogs = app.displayDialogs;
                app.displayDialogs = DialogModes.NO;

                // TIFF save options
                var tiffSaveOptions = new TiffSaveOptions();
                tiffSaveOptions.imageCompression = TIFFEncoding.NONE; // TIFFLZW | TIFFZIP | JPEG
                tiffSaveOptions.embedColorProfile = true;
                tiffSaveOptions.byteOrder = ByteOrder.IBM;
                tiffSaveOptions.transparency = true;
                tiffSaveOptions.layers = true;
                tiffSaveOptions.layerCompression = LayerCompression.ZIP;
                tiffSaveOptions.interleaveChannels = true;
                tiffSaveOptions.alphaChannels = true;
                tiffSaveOptions.annotations = true;
                tiffSaveOptions.spotColors = true;
                tiffSaveOptions.saveImagePyramid = false;

                // Hide the Photoshop panels
                app.togglePalettes();

                // Script running notification window - courtesy of William Campbell
                /* https://www.marspremedia.com/download?asset=adobe-script-tutorial-11.zip
                   https://youtu.be/JXPeLi6uPv4?si=Qx0OVNLAOzDrYPB4 */
                var working;
                working = new Window("palette");
                working.preferredSize = [300, 80];
                working.add("statictext");
                working.t = working.add("statictext");
                working.add("statictext");
                working.display = function (message) {
                    this.t.text = message || "Script running, please wait...";
                    this.show();
                    app.refresh();
                };
                working.display();

                // Set the file processing counter
                var counter = 0;

                // Perform the stacking and saving
                for (var i = 0; i < list1.length; i++) {
                    var doc = open(list1[i]);
                    var docName = doc.name.replace(/\.[^\.]+$/, '');
                    placeFile(list2[i], 100);
                    resetTransforms();
                    app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
                    app.activeDocument.activeLayer.opacity = 40; // Layer opacity
                    selectAllLayers();
                    autoAlign();
                    cropTransparency(); // Optional crop
                    app.activeDocument.saveAs(new File(saveFolder + '/' + docName + '_Merged' + '.tif'), tiffSaveOptions);
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                    counter++; // Increment the counter
                }

                // Ensure Photoshop has focus before closing the running script notification window
                app.bringToFront();
                working.close();

                // End of script notification
                app.displayDialogs = savedDisplayDialogs;
                app.beep();
                alert('Script completed!' + '\r' + counter + ' merged TIFF files saved to:' + '\r' + saveFolder.fsName);

                // Restore the Photoshop panels
                app.togglePalettes();

            } catch (err) {
                while (app.documents.length > 0) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }
                alert("Error!" + "\r" + err + ' ' + err.line);
            }

        } else {
            alert('Please close all open documents before running this script!');
        }


        ///// Functions /////

        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) { }
        }

        function resetTransforms() {
            try {
                var idplacedLayerResetTransforms = stringIDToTypeID("placedLayerResetTransforms");
                executeAction(idplacedLayerResetTransforms, undefined, DialogModes.NO);
            } catch (e) {
                //alert("Error!" + "\r" + e + ' ' + e.line); // Errors in 2019 version
                app.refresh();
            }
        }

        function selectAllLayers() {
            try {
                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();
                var reference2 = new ActionReference();
                reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(c2t("null"), reference2);
                executeAction(s2t("selectAllLayers"), descriptor, DialogModes.NO);
                // Add the Background layer if it exists
                reference.putProperty(s2t("layer"), s2t("background"));
                descriptor2.putReference(c2t("null"), reference);
                descriptor2.putEnumerated(s2t("selectionModifier"), s2t("selectionModifierType"), s2t("addToSelection"));
                descriptor2.putBoolean(s2t("makeVisible"), false);
                executeAction(s2t("select"), descriptor2, DialogModes.NO);
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

        function autoAlign() {
            try {
                var desc = new ActionDescriptor();
                var ref = new ActionReference();
                ref.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
                desc.putReference(charIDToTypeID('null'), ref);
                desc.putEnumerated(charIDToTypeID('Usng'), charIDToTypeID('ADSt'), stringIDToTypeID('ADSContent'));
                desc.putEnumerated(charIDToTypeID('Aply'), stringIDToTypeID('projection'), charIDToTypeID('Auto'));
                desc.putBoolean(stringIDToTypeID('vignette'), false);
                desc.putBoolean(stringIDToTypeID('radialDistort'), false);
                executeAction(charIDToTypeID('Algn'), desc, DialogModes.NO);
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

        function cropTransparency() {
            try {
                var s2t = function (s) {
                    return app.stringIDToTypeID(s);
                };
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();
                var descriptor3 = new ActionDescriptor();
                var descriptor4 = new ActionDescriptor();
                var descriptor5 = new ActionDescriptor();
                var descriptor6 = new ActionDescriptor();
                var reference = new ActionReference();
                var reference2 = new ActionReference();
                var reference3 = new ActionReference();
                var reference4 = new ActionReference();
                // Dupe layers to temp merged layer
                descriptor.putBoolean(s2t("duplicate"), true);
                executeAction(s2t("mergeLayersNew"), descriptor, DialogModes.NO);
                // Load selection from layer transparency
                reference.putProperty(s2t("channel"), s2t("selection"));
                descriptor2.putReference(s2t("null"), reference);
                reference2.putEnumerated(s2t("channel"), s2t("channel"), s2t("transparencyEnum"));
                descriptor2.putReference(s2t("to"), reference2);
                executeAction(s2t("set"), descriptor2, DialogModes.NO);
                // Enter quick mask mode
                reference3.putProperty(s2t("property"), s2t("quickMask"));
                reference3.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
                descriptor3.putReference(s2t("null"), reference3);
                // Threshold to 255 levels
                executeAction(s2t("set"), descriptor3, DialogModes.NO);
                descriptor4.putInteger(s2t("level"), 255);
                executeAction(s2t("thresholdClassEvent"), descriptor4, DialogModes.NO);
                // Exit quick mask mode
                reference4.putProperty(s2t("property"), s2t("quickMask"));
                reference4.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
                descriptor5.putReference(s2t("null"), reference4);
                // Crop selection
                executeAction(s2t("clearEvent"), descriptor5, DialogModes.NO);
                descriptor6.putBoolean(s2t("delete"), true);
                executeAction(s2t("crop"), descriptor6, DialogModes.NO);
                // Clean up
                app.activeDocument.activeLayer.remove();
                app.activeDocument.selection.deselect();
            } catch (e) {
                alert("Error!" + "\r" + e + ' ' + e.line);
            }
        }

    }());

 

Instructions for saving and use:

 

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

 

Known Participant
July 17, 2024

Awesome, appreciate that very much. Let me give it a shot and see how it does. Should be a huge time saver. 

Legend
July 16, 2024

Why not just use an HDR feature for blending? And I don't get why you would blend an edited and unedited shot.

I just use adjustment layers with masking and am able to get pretty much any effect. Its rare that I blend multiple exposures unless I'm doing a panorama.

Stephen Marsh
Community Expert
Community Expert
July 16, 2024

@jonathanb67250519 

 

I have a couple of generic batch scripts posted here:

 

 
The scripts are designed to fast-track the development of custom scripts, as they perform the basic processing. These versions don't auto-align, they expect that the files are the same size and that the content is aligned. The script assumes alphabetically sorting file pairs from a single folder or top-level folder + sub-folders. It's also possible to select 2 different source folders. It's hard to make a generic script cover all workflows, however, I am happy to change things as needed if you can't adapt your workflow to the script.
 
You will first need to use Lr or ACR to batch render the raw files to an appropriate format such as TIFF or PSD.
 
The script can call an action, so if you find it easier to do the processing of the two stacked layers via an action then you don't need to know how to script those steps.
 
I did look at auto-align in this script:
 
 
c.pfaffenbichler
Community Expert
Community Expert
July 16, 2024

I wonder, though, to what end one would need to align the RAW and the jpg – which makes me wonder whether I understood the OP’s intended process. 

Stephen Marsh
Community Expert
Community Expert
July 16, 2024

hopefully that action helped clarify the auto align step, if not, let me know. thanks


The action download has been deleted, however, if you say that you use the Auto setting then that is all I need to know, a screenshot would suffice if that is the only thing that you do to auto-align the two layers.

c.pfaffenbichler
Community Expert
Community Expert
July 16, 2024

Please provide sample images or at least meaningful screenshots to illustrate the process, the imagery, the file structure and the naming convention. 

 

It sounds like a case for Photoshop Scripting; several Scripts have been posted about combining X images.