Skip to main content
Known Participant
February 4, 2022
Answered

PNG and JPEG clipping mask.

  • February 4, 2022
  • 3 replies
  • 1161 views

Hi all! This time things got even more difficult for my knowledge of Actions and scripts. The situation is as follows: I receive jpeg and png files, in different folders and subfolders. PNGs are clipping masks, which must be applied to JPEGs. The files have the same name, what changes is only the extension. Is it possible for a script, action, or both to open the jpegs, get the corresponding PNGs in the other folder, apply them as a mask on the JPEG to remove the background, and save the file as jpeg (final) in another folder?
It could be separated too, the most important thing is to apply the PNG masks to the JPEGs. A script that recognizes the same names in the folder, opens and places the PNG inside the JPEG, would be of great help. The rest I think would be possible with Actions/Batch, right?

Thank you all for the help!

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

A common request, so a fairly quick edit to a previous script delivered the following script. I have added an _Masked to the filename to avoid accidentally overwriting existing files. If this is unwanted, it should be easy to remove with the example in lines 80-81.

 

/*
Mask JPG files using PNG files from 2 input folders.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/png-and-jpeg-clipping-mask/m-p/12730278#M621037
Stephen Marsh, v1.0 - 5th February 2022
*/

#target photoshop

(function () {

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

        try {

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

            // PNG image input folder
            var folder2 = Folder.selectDialog("Select the PNG mask 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;
            }

            // Limit the file input formats
            var list1 = folder1.getFiles(/\.(jpg|jpeg)$/i);
            var list2 = folder2.getFiles(/\.(png)$/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;

            // JPEG save options
            var jpgOptions = new JPEGSaveOptions();
            jpgOptions.formatOptions = FormatOptions.STANDARDBASELINE;
            jpgOptions.embedColorProfile = true;
            jpgOptions.matte = MatteType.NONE;
            jpgOptions.quality = 11;

            // 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);
                channelSelection();
                app.activeDocument.activeLayer.remove();
                maskSelection("revealSelection");
                doc.saveAs(new File(saveFolder + '/' + docName + '_Masked' + '.jpg'), jpgOptions);
                //doc.saveAs(new File(saveFolder + '/' + docName + '.jpg'), jpgOptions);
                doc.close(SaveOptions.DONOTSAVECHANGES);
            }

            // End of script
            app.displayDialogs = savedDisplayDialogs;
            app.beep();
            var listCount = list1.length;
            alert('Script completed!' + '\r' + listCount + ' JPEG files saved to:' + '\r' + saveFolder.fsName);

        } catch (err) {
            while (app.documents.length > 0) {
                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
            }
            alert("An unexpected error has occurred!");
        }

    } 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 channelSelection() {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        var reference = new ActionReference();
        var reference2 = new ActionReference();
        reference.putProperty(s2t("channel"), s2t("selection"));
        descriptor.putReference(s2t("null"), reference);
        reference2.putEnumerated(s2t("channel"), s2t("channel"), s2t("grain"));
        descriptor.putReference(s2t("to"), reference2);
        executeAction(s2t("set"), descriptor, DialogModes.NO);
    }

    function maskSelection(maskParameter) {
        // Parameter = "revealSelection" or "hideSelection"
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        var reference = new ActionReference();
        descriptor.putClass(s2t("new"), s2t("channel"));
        reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
        descriptor.putReference(s2t("at"), reference);
        descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t(maskParameter));
        executeAction(s2t("make"), descriptor, DialogModes.NO);
    }

}());

 

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

 

3 replies

rrprecAuthor
Known Participant
February 8, 2022

We made some changes to the folders so the script works as we need it. Thanks to all of you for the huge help!

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
February 4, 2022

A common request, so a fairly quick edit to a previous script delivered the following script. I have added an _Masked to the filename to avoid accidentally overwriting existing files. If this is unwanted, it should be easy to remove with the example in lines 80-81.

 

/*
Mask JPG files using PNG files from 2 input folders.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/png-and-jpeg-clipping-mask/m-p/12730278#M621037
Stephen Marsh, v1.0 - 5th February 2022
*/

#target photoshop

(function () {

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

        try {

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

            // PNG image input folder
            var folder2 = Folder.selectDialog("Select the PNG mask 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;
            }

            // Limit the file input formats
            var list1 = folder1.getFiles(/\.(jpg|jpeg)$/i);
            var list2 = folder2.getFiles(/\.(png)$/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;

            // JPEG save options
            var jpgOptions = new JPEGSaveOptions();
            jpgOptions.formatOptions = FormatOptions.STANDARDBASELINE;
            jpgOptions.embedColorProfile = true;
            jpgOptions.matte = MatteType.NONE;
            jpgOptions.quality = 11;

            // 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);
                channelSelection();
                app.activeDocument.activeLayer.remove();
                maskSelection("revealSelection");
                doc.saveAs(new File(saveFolder + '/' + docName + '_Masked' + '.jpg'), jpgOptions);
                //doc.saveAs(new File(saveFolder + '/' + docName + '.jpg'), jpgOptions);
                doc.close(SaveOptions.DONOTSAVECHANGES);
            }

            // End of script
            app.displayDialogs = savedDisplayDialogs;
            app.beep();
            var listCount = list1.length;
            alert('Script completed!' + '\r' + listCount + ' JPEG files saved to:' + '\r' + saveFolder.fsName);

        } catch (err) {
            while (app.documents.length > 0) {
                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
            }
            alert("An unexpected error has occurred!");
        }

    } 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 channelSelection() {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        var reference = new ActionReference();
        var reference2 = new ActionReference();
        reference.putProperty(s2t("channel"), s2t("selection"));
        descriptor.putReference(s2t("null"), reference);
        reference2.putEnumerated(s2t("channel"), s2t("channel"), s2t("grain"));
        descriptor.putReference(s2t("to"), reference2);
        executeAction(s2t("set"), descriptor, DialogModes.NO);
    }

    function maskSelection(maskParameter) {
        // Parameter = "revealSelection" or "hideSelection"
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        var reference = new ActionReference();
        descriptor.putClass(s2t("new"), s2t("channel"));
        reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
        descriptor.putReference(s2t("at"), reference);
        descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t(maskParameter));
        executeAction(s2t("make"), descriptor, DialogModes.NO);
    }

}());

 

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

 

rrprecAuthor
Known Participant
February 7, 2022

Thank you Stephen and Kukurykus. The script works, but only if I have the files separated into folders, with the same number of images. Unfortunately, the files are in subfolders, scattered around, and together with other files. Is it possible to do something like a droplet, and throw all the folders, and the script recognize the JPEGs and PNGs by name in the subfolders, and apply the masks?

thanks again

c.pfaffenbichler
Community Expert
Community Expert
February 7, 2022

Maybe you could post meaningful screenshots to illustrate the file and folder naming and locations? 

Kukurykus
Legend
February 4, 2022