• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Importing Remove.bg files as smart object layer including the layermask

Participant ,
Jun 24, 2024 Jun 24, 2024

Copy link to clipboard

Copied

A while back @Stephen_A_Marsh created a script for me to import Remove.bg files as layers including a layermask into a template file. At that time, and for that particular case, making the image a smart object was not desirable. It would interfere with the warping process. See the original post here (including examples)

 

But now I want to re-use the script for a slightly different flow and wish to have the imported layer be a smart object of the original image and, on top of it, the layer mask.

 

Is somebody or perhaps the master@Stephen_A_Marsh himself 😅 Able to assist me?

 

 

 

 

/*
Stack Masked Doc Layers to Template Doc.jsx
v1.0 - 21st May 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-import-warp-resize-and-move-layers/td-p/14623443
*/

#target photoshop

function main() {

    (function () {

        try {
            var savedRuler = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.PIXELS;

            // Set the active doc as the template doc
            var templateDoc = app.activeDocument;
            var templateDocName = app.activeDocument.name;

            // Ensure that the contents of the PHOTOS group is active
            if (app.activeDocument.activeLayer.name != 'PHOTOS') {
                app.activeDocument.activeLayer = app.activeDocument.layerSets.getByName('PHOTOS').layers[0];
            }

            // Select the 'remove.bg' PSD source files
            var selectFile = File.openDialog('Select the file/s:', Multiselect = true);
            if (selectFile === null) {
                return;
            }

            // Loop over the selected files
            for (var i = 0; i < selectFile.length; i++) {

                // Open each selected file
                app.open(File(selectFile[i]));

                // Set the sourceDoc as the active document
                var sourceDoc = app.activeDocument;

                // Select the source layer
                //app.activeDocument.activeLayer = app.activeDocument.layers.getByName('remove.bg');
                app.activeDocument.activeLayer = app.activeDocument.layers[0];

                // Ensure that the RGB channels are selected and not the layer mask
                app.activeDocument.activeChannels = app.activeDocument.componentChannels;

                // Apply the Background to the remove.bg layer
                var s2t = function (s) {
                    return app.stringIDToTypeID(s);
                };
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();
                var reference = new ActionReference();
                reference.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "RGB" ));
                reference.putName( s2t( "layer" ), "Background" );
                descriptor2.putReference( s2t( "to" ), reference );
                descriptor.putObject( s2t( "with" ), s2t( "calculation" ), descriptor2 );
                executeAction( s2t( "applyImageEvent" ), descriptor, DialogModes.NO );

                // Duplicate the source layer to the template doc
                dupeLayer(templateDocName, app.activeDocument.name.replace(/\.[^\.]+$/, ''));

                // Set the template doc as the active document
                app.activeDocument = templateDoc;

                // Conditionally resize the layer to fit the canvas
                var docWidth = app.activeDocument.width;
                var docHeight = app.activeDocument.height;
                var layerWidth = (app.activeDocument.activeLayer.bounds[2].value - app.activeDocument.activeLayer.bounds[0].value);
                var layerHeight = (app.activeDocument.activeLayer.bounds[3].value - app.activeDocument.activeLayer.bounds[1].value);
                if (layerWidth > docWidth) {
                    //alert('The layer is wider than the canvas!');
                    app.activeDocument.activeLayer.resize((docWidth / layerWidth) * 100, (docWidth / layerWidth) * 100, AnchorPosition.MIDDLECENTER);
                }
                if (layerHeight > docHeight) {
                    //alert('The layer is taller than the canvas!');
                    app.activeDocument.activeLayer.resize((docHeight / layerHeight) * 100, (docHeight / layerHeight) * 100, AnchorPosition.MIDDLECENTER);
                }

                // Centre the duped layer on the template canvas
                app.activeDocument.activeLayer.translate(docWidth / 2 - (app.activeDocument.activeLayer.bounds[0] + app.activeDocument.activeLayer.bounds[2]) / 2,
                    docHeight / 2 - (app.activeDocument.activeLayer.bounds[1] + app.activeDocument.activeLayer.bounds[3]) / 2);

                // Close the source doc
                sourceDoc.close(SaveOptions.DONOTSAVECHANGES);

            }

            app.preferences.rulerUnits = savedRuler;


            // Functions

            function dupeLayer(targetDocName, sourceLayerName) {
                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var list = new ActionList();
                var reference = new ActionReference();
                var reference2 = new ActionReference();
                reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(s2t("null"), reference);
                reference2.putName(s2t("document"), targetDocName);
                descriptor.putReference(s2t("to"), reference2);
                descriptor.putString(s2t("name"), sourceLayerName);
                descriptor.putList(s2t("ID"), list);
                executeAction(s2t("duplicate"), descriptor, DialogModes.NO);
            }

        } catch (e) {
            alert('Error!' + '\r' + e + ', Line: ' + e.line);
        }

    })();

}


main();

 

  

TOPICS
Actions and scripting , macOS

Views

77

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Jun 24, 2024 Jun 24, 2024

Copy link to clipboard

Copied

@Esther Netherlands 

 

Try the following version:

 

/*
Stack Masked Doc Layers as Smart Objects to Template Doc.jsx
v1.0 - 25th June 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-import-warp-resize-and-move-layers/td-p/14623443
*/

#target photoshop

if (app.documents.length) {

    (function () {
        if (app.activeDocument.name == 'Framefoto-template.psd') {
            main();
        } else {
            var theConfirmation = (confirm("The active doc isn't named 'Framefoto-template.psd' Continue?", false));
            if (theConfirmation === false) {
                return;
            }
            main();
        }
    })();

} else {
    alert('A document must be open to run this script!');
}


function main() {

    (function () {

        try {
            var savedRuler = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.PIXELS;

            // Set the active doc as the template doc
            var templateDoc = app.activeDocument;
            var templateDocName = app.activeDocument.name;

            // Ensure that the contents of the FOTO group is active
            if (app.activeDocument.activeLayer.name != 'FOTOS') {
                app.activeDocument.activeLayer = app.activeDocument.layerSets.getByName('FOTOS').layers[0];
            }

            // Select the 'remove.bg' PSD source files
            var selectFile = File.openDialog('Select the file/s:', Multiselect = true);
            if (selectFile === null) {
                return;
            }

            // Start processing
            app.togglePalettes();

            // Loop over the selected files
            for (var i = 0; i < selectFile.length; i++) {

                // Open each selected file
                app.open(File(selectFile[i]));

                // Set the sourceDoc as the active document
                var sourceDoc = app.activeDocument;
                
                ///// 25th June 2024 - Convert the 'remove.bg' layer stack to a smart object /////
                 if (app.activeDocument.layers[app.activeDocument.layers.length - 1].isBackgroundLayer) {
                    app.activeDocument.layers[app.activeDocument.layers.length - 1].name = 'Background';
                }
                app.activeDocument.layers[app.activeDocument.layers.length - 1].allLocked = false;
                app.runMenuItem(stringIDToTypeID('selectAllLayers'));
                executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);
                app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                app.activeDocument.layers[app.activeDocument.layers.length - 1].allLocked = true;
                app.activeDocument.layers[app.activeDocument.layers.length - 1].visible = false;
                activeDocument.close(SaveOptions.SAVECHANGES);
                /////

                // Duplicate the source layer to the template doc
                dupeLayer(templateDocName, app.activeDocument.name.replace(/\.[^\.]+$/, ''));

                // Set the template doc as the active document
                app.activeDocument = templateDoc;

                // Conditionally resize the layer to fit the canvas
                var docWidth = app.activeDocument.width;
                var docHeight = app.activeDocument.height;
                var layerWidth = (app.activeDocument.activeLayer.bounds[2].value - app.activeDocument.activeLayer.bounds[0].value);
                var layerHeight = (app.activeDocument.activeLayer.bounds[3].value - app.activeDocument.activeLayer.bounds[1].value);
                if (layerWidth > docWidth) {
                    //alert('The layer is wider than the canvas!');
                    app.activeDocument.activeLayer.resize((docWidth / layerWidth) * 100, (docWidth / layerWidth) * 100, AnchorPosition.MIDDLECENTER);
                }
                if (layerHeight > docHeight) {
                    //alert('The layer is taller than the canvas!');
                    app.activeDocument.activeLayer.resize((docHeight / layerHeight) * 100, (docHeight / layerHeight) * 100, AnchorPosition.MIDDLECENTER);
                }

                // Centre the duped layer on the template canvas
                app.activeDocument.activeLayer.translate(docWidth / 2 - (app.activeDocument.activeLayer.bounds[0] + app.activeDocument.activeLayer.bounds[2]) / 2,
                    docHeight / 2 - (app.activeDocument.activeLayer.bounds[1] + app.activeDocument.activeLayer.bounds[3]) / 2);

                // Close the source doc
                sourceDoc.close(SaveOptions.DONOTSAVECHANGES);

            }

            app.preferences.rulerUnits = savedRuler;

            // End of processing
            app.togglePalettes();
            app.beep();


            // Functions

            function dupeLayer(targetDocName, sourceLayerName) {
                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var list = new ActionList();
                var reference = new ActionReference();
                var reference2 = new ActionReference();
                reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(s2t("null"), reference);
                reference2.putName(s2t("document"), targetDocName);
                descriptor.putReference(s2t("to"), reference2);
                descriptor.putString(s2t("name"), sourceLayerName);
                descriptor.putList(s2t("ID"), list);
                executeAction(s2t("duplicate"), descriptor, DialogModes.NO);
            }

            function selectAllLayers() {
                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);
                try {
                    // 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);
                }
            }

        } catch (e) {
            alert('Error!' + '\r' + e + ', Line: ' + e.line);
        }

    })();

}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jun 25, 2024 Jun 25, 2024

Copy link to clipboard

Copied

Thanks, @Stephen_A_Marsh 

It does work, but I was looking to keep the layer masks and have these on top of the smart object.


I was able to get it to work using your initial code, ChatGPT, and some Frankenstein assembly 🫣

 

I did remove

  • #target photoshop - For some reason, my Visual Studio always sees this as an error. I'm curious as to why it is always used, though.
  • The check on the template name due to this one being used for multiple "bases."
  • I moved the resize to a separate script so I can make base-specific ones. Or would you recommend to always do it in 1 script for specific reasons #eagertolearn 🤓

 

/* 
25-06-2024 Stack Masked Doc Layers to Template Doc by Stephen Marsh, mailesther010@gmail.com and ChatGPT
https://community.adobe.com/t5/photoshop-ecosystem-discussions/importing-remove-bg-files-as-smart-object-layer-including-the-layermask/m-p/14700531#M817361
*/

function main() {

    (function () {

        try {
            var savedRuler = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.PIXELS;

            // Set the active doc as the template doc
            var templateDoc = app.activeDocument;
            var templateDocName = app.activeDocument.name;

            // Ensure that the contents of the PHOTOS group is active
            if (app.activeDocument.activeLayer.name != 'PHOTOS') {
                app.activeDocument.activeLayer = app.activeDocument.layerSets.getByName('PHOTOS').layers[0];
            }

            // Select the 'remove.bg' PSD source files
            var selectFile = File.openDialog('Select the file/s:', Multiselect = true);
            if (selectFile === null) {
                return;
            }

            // Loop over the selected files
            for (var i = 0; i < selectFile.length; i++) {

                // Open each selected file
                app.open(File(selectFile[i]));

                // Set the sourceDoc as the active document
                var sourceDoc = app.activeDocument;
                var firstLayer = sourceDoc.layers[0];;
                var secondLayer = sourceDoc.layers[1];

                // Select and convert the second layer to a smart object
                sourceDoc.activeLayer = secondLayer
                makeSmartObject();

                // Copy the layer mask from the first layer and apply it to the second layer
                sourceDoc.activeLayer = firstLayer
                moveLayerMask("remove.bg", "remove.bg - Original Image");

                // Duplicate layer to the template doc
                app.activeDocument.activeLayer = app.activeDocument.layers[1];
                dupeLayer(templateDocName, app.activeDocument.name.replace(/\.[^\.]+$/, ''));

                // Set the template doc as the active document
                app.activeDocument = templateDoc;
                
                // Deselect the selection
                app.activeDocument.selection.deselect();

                // Close the source doc
                sourceDoc.close(SaveOptions.DONOTSAVECHANGES);

            }

            app.preferences.rulerUnits = savedRuler;

            // Functions

            function dupeLayer(targetDocName, sourceLayerName) {
                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var list = new ActionList();
                var reference = new ActionReference();
                var reference2 = new ActionReference();
                reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                descriptor.putReference(s2t("null"), reference);
                reference2.putName(s2t("document"), targetDocName);
                descriptor.putReference(s2t("to"), reference2);
                descriptor.putString(s2t("name"), sourceLayerName);
                descriptor.putList(s2t("ID"), list);
                executeAction(s2t("duplicate"), descriptor, DialogModes.NO);
            }

            function makeSmartObject() {
                var idnewPlacedLayer = stringIDToTypeID("newPlacedLayer");
                executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
            }

            function moveLayerMask(sourceLayerName, targetLayerName) {
                function cTID(s) { return app.charIDToTypeID(s); };

                var desc8 = new ActionDescriptor();
                desc8.putClass(cTID('Nw  '), cTID('Chnl'));
                var ref5 = new ActionReference();
                ref5.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
                ref5.putName(cTID('Lyr '), "remove.bg - Original Image");
                desc8.putReference(cTID('At  '), ref5);
                var ref6 = new ActionReference();
                ref6.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
                ref6.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
                desc8.putReference(cTID('Usng'), ref6);
                executeAction(cTID('Mk  '), desc8, DialogModes.NO);
            }

            function stringIDToTypeID(str) {
                return app.stringIDToTypeID(str);
            }


        } catch (e) {
            alert('Error!' + '\r' + e + ', Line: ' + e.line);
        }

    })();

}

main();

 

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 25, 2024 Jun 25, 2024

Copy link to clipboard

Copied

quote

Thanks, @Stephen_A_Marsh 

It does work, but I was looking to keep the layer masks and have these on top of the smart object.

 

My bad, I missed that.

 

quote

Thanks, @Stephen_A_Marsh 

It does work, but I was looking to keep the layer masks and have these on top of the smart object.


I was able to get it to work using your initial code, ChatGPT, and some Frankenstein assembly 🫣

 

I did remove

  • #target photoshop - For some reason, my Visual Studio always sees this as an error. I'm curious as to why it is always used, though.
  •  

 

The #target app/version is a throwback to .jsx scripts being associated with the old ESTK app, so that you can have your cake and eat it (having the script passed onto say Photoshop even though it was opened by the ESTK app). You are correct that VS Code doesn't like it. I usually just // comment it out and then remove the comment double-slashes when I'm done with VS Code. In addition to defining the target app from an outdated legacy script execution perspective, it also provides a hopefully "obvious" clue to less knowledgeable end-users as to which app the script is intended to be run in. An alternative would be to use the less common BridgeTalk.appName block.

 

 

quote
  • I moved the resize to a separate script so I can make base-specific ones. Or would you recommend to always do it in 1 script for specific reasons #eagertolearn 🤓

By @Esther Netherlands

 

Do what works for you!

 

You can have one script call another script or have an action call multiple scripts in sequence.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 05, 2024 Jul 05, 2024

Copy link to clipboard

Copied

LATEST

Hey @Stephen_A_Marsh Apologies for missing your reply! Thank you so very much for taking the time to explain the need / reason of #target photoshop. Although I am not a real scripter, I learned a lot from you and your codes 🙏🏻 Thanksss!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines