Skip to main content
Known Participant
April 23, 2021
Question

Photoshop script to auto stack pair of images, then auto-align, and export.

  • April 23, 2021
  • 3 replies
  • 6447 views

I have shots comprised of jpg image sequences.  I'm processing the shots.  When I process them, position and scale for a portion of the image is offset.  I'm trying to use a script to perspective auto align the processed image to match the original image.

 

So I believe I need a script to:

1.  Load original image into layer 1.

2.  Load processed image into layer 2.

3.  Designate the original image on layer 1 as the reference, so that the processed image on layer 2 is perpective transformed to match the original image on layer 1.

4.  Auto-align layer 2 to layer 1.

5.  Export the aligned layers, with layer 2 on top, to an uncompressed file (not .psd).

6.  Repeat script on each matched pair until all pairs in the folders are procesed.

 

I assume the folder structures should be:

 

"Folder 1" = original files (contains the first set of matched pairs identically named as their match in folder 2).

"Folder 2" = processed files (contains the other set of matched pairs identically named as their match in folder 1).

"Output Folder" = photoshop aligned exported file.

 

FYI - The processed image is only the portion of the frame that has been position and scale offset by the processing.  So the result I'm looking for is exactly what photoshop does when you manually auto-align the two uploaded images.  I don't want the processed image to be auto-aligned to full frame, just aligned against the portion of the original image that came from.

 

I have found a plugin called Image Processor Pro, that will auto process every image in a folder.  I've also found a script that I think will stack images in adobe bridge, but it's 10 years old, for Windows 7.

 

I just can't think of the right combination of search terms for google.  This has to be out there somwhere.

 

Totally willing to pay for your time for a solution.  We can DM or Discord, or something.

 

Thanks!

This topic has been closed for replies.

3 replies

Stephen Marsh
Community Expert
Community Expert
April 24, 2021

 

@whitebalanceinc 

 

Try this modification to the script that I pointed to earlier in the thread:

 

 

/*
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.3 - 26th April 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);
                app.activeDocument.activeLayer.allLocked = true;

                placeFile(list2[i], 100);
                app.runMenuItem(stringIDToTypeID('rasterizePlaced'));
                app.runMenuItem(stringIDToTypeID("selectAllLayers"));
                // Auto = "auto", Reposition = "translation"
                autoAlignLayers(false, "auto", false, false);

                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 autoAlignLayers(alignToCanvas, projValue, vignette, radialDistort) {
                var c2t = function (s) {
                    return app.charIDToTypeID(s);
                }
                var s2t = function (s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var reference = new ActionReference();
                reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(c2t("null"), reference);
                descriptor.putEnumerated(s2t("using"), s2t("alignDistributeSelector"), s2t("ADSContent"));
                descriptor.putBoolean(s2t("alignToCanvas"), alignToCanvas);
                // projValue - Auto = "auto", Reposition = "translation"
                descriptor.putEnumerated(s2t("apply"), s2t("projection"), s2t(projValue));
                descriptor.putBoolean(s2t("vignette"), vignette);
                descriptor.putBoolean(s2t("radialDistort"), radialDistort);
                executeAction(c2t("Algn"), descriptor, 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!');

        }

    }());

 

 

Instructions for saving/running scripts here:

 

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

 

Known Participant
April 24, 2021

Hello @Stephen Marsh 

 

Wow!!!!  That was a fast response!  Thank you!  The script is almost perfect!

 

When I run my image sequence through the script, photoshop is changing the scale and position of both the original and the processed files so they align.  Sometimes shrinking the original and blowing up the processed file, morhping them both to meet in the middle so they align.

 

The perspective shift is happening (instead of just a position shift) because my processed files are actually slightly different in shape and size then the originals.  So "auto" mode adds the perspective morph.

 

Is there anyway to lock the original's layer so that it does not change, and only the processed layer is morphed to align?

 

Again thanks so much!

Stephen Marsh
Community Expert
Community Expert
May 6, 2021

Hi @Stephen Marsh,

I'll try a relative instead of absolute.  The main issue is not having to select each image, one at a time.  There could be tens of thousands of frames.

 

Are you saying the background is no longer changing?  It remains locked?  Then my thought is maybe pause before auto-align and after the auto-align feature.  Maybe there needs to be time for PS to think?


 

The differences in stacking that I am seeing may only be due to your pre-processing and JPG vs. TIFF.

 

What I'm thinking is that If the action works for you when the script previously provided does not, then new script can run the action. I can't keep flogging this dead horse, I have to close this project.

 

Example of your .atn file modified for use in my script. I still have to adjust the script code to suit:

 

 

Download link to action set:

 

https://shared-assets.adobe.com/link/a8800853-6e09-4f39-4d3e-71569bebab33

 

JJMack
Community Expert
Community Expert
April 23, 2021

You would need he explain what your step 3 is in great detail.

"3.  Designate the original image on layer 1 as the reference, so that the processed image on layer 2 is perpective transformed to match the original image on layer 1."

How do you want to distort image 2 to match some projective that image 1 has to be able to align something. Are you trying to stitch images or do some kind of stack mode blending?

 

Have you tried any of Photoshop features like Photomerge and stack mode blending?

 

JJMack
Known Participant
April 24, 2021

Hello @JJMack  and @Stephen Marsh ,

 

Thank you for asking for clarification.  Here is what I would like a script to do:

 

Step 1:  Open Photoshop.

Step 2:  Load the first pair of images into a stack, so that the original image is on the bottom layer, and the processed image is on the top layer.  This can be done with the stack images script or place embed command.  But it seems to save steps with the stack image script.  Once stacked they should look like this:
 
Step 3:  Select both layers, choose Auto-Align Layers (no blending), using the "auto" setting.
Step 4:  Export with the same file name to .tiff with these settings:
So that the final output image looks like this:
5.  Repeat until all matched pairs are auto aligned.
 
Would be awesome of the script could work on both Mojave and Windows 10, but if I have to choose, Windows 10.
 
Here are links to Google Drive, of the originals, processed image, and output from photoshop:
Original Images:
Processed Images:
The output of the three sets of matched pairs (original and processed) should look like when auto-aligned:
 
No need to blend, crop, resize, or anything, simply auto-align the the pairs, and export.
 
Thanks so much!!
Stephen Marsh
Community Expert
Community Expert
April 24, 2021

Thanks, that is perfect!

 

I should be able to easily modify an existing script for your purposes.

 

 

Stephen Marsh
Community Expert
Community Expert
April 23, 2021

It would be very helpful if you could upload sample images to the forum, your CC share, Dropbox etc.

 

Sample filenames showing how each pair or sequence of images can be automatically determined. 

 

Additionally if you can post cropped screenshots of the settings that you are happy with when doing this manually.