Skip to main content
Participant
October 31, 2019
Answered

ExtendScript Photoshop Edit Contents Smart Layer

  • October 31, 2019
  • 6 replies
  • 17589 views

I have a psd file with an embedded psd file. Using photoshop normally, I double on the layer icon to edit the contents (or choose "edit contents" from the dropdown). I can not seem to find out how to open/edit it with extendscript/javascript. It is a legend that we use on our plans and would like to add content via scripting but need to find out how to edit the contents first. Note: this is not a linked file externally, it is embedded.

Thanks in advance.

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

One way:

 

app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));

 

https://community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/m-p/10644877

6 replies

JJMack
Community Expert
Community Expert
January 5, 2021

yes you fixed it

JJMack
pixxxelschubser
Community Expert
Community Expert
January 5, 2021



@schroef  wrote:
"… Sorry my message didnt post a couple times, then i got some kind of ban and needed to wait a hour. Kinda stupid dumb it does a page refresh and not post the message. Twice did i made a long new post, both times lost 

:(

 This forum still isnt working really well i guess. …"


test

schroef
Inspiring
January 6, 2021

@pixxxelschubser 

thanks for trying, i just posted my experience above and added some comments about what happened.

Sadly i didnt screengrab every error i got. Only the "wrong/bad HTML" code error

Sil.C
Community Manager
Community Manager
January 5, 2021

test

schroef
Inspiring
January 6, 2021

This issue happened when i was posting message quite fast within the hour. Thats also why i got the "wait 3600 second" warning/error.

 

I also see a lot of errors when i post code which have comments in them from either community links or other website. It then shows an error about "faulty html" code or so. I did make a screengrab of that error i get a lot when pasting script as Javascript. Sometimes when i checked the pasted script, i noticed parts where missing. But also i noticed sometimes parts where added. I looked like it grabbed text of the forum link i pasted in the script as a comment.



What i did see a lot was that when i pressed post, the page would reload and nothing showed. No error not hint of bad embed text nothing, my complete message was gone. This happened quite a lot of times. Then eventually after witing a day i still could reply to a post made by JJMack. I could only reply to the main question on top.

Could it be that threads have some kind of limit of responses? Because i was posting quite a lot script code each time, perhaps there something like a "max character count", i dont know. You would need to ask the developers of the forum.

The fact that you think its posting and it doesnt is nasty. You cant go back and you basically lost your complete message.

 

 Hope this helps to understand what i was experiencing and perhaps can help to backtrack the issue.

 

PS there was actually another weird error i got. Its an error where it also stated that "invalid HTML" is used and that its being highlighted, yet nothing is highlighted then?!

schroef
Inspiring
January 5, 2021
 
Sorry my message didnt post a couple times, then i got some kind of ban and needed to wait a hour. Kinda stupid dumb it does a page refresh and not post the message. Twice did i made a long new post, both times lost 😞 This forum still isnt working really well i guess.


Anyways here's the link. https://we.tl/t-amPqhIM4pC
I had it ready forgot about, but than it also got delete twice because of the prior post issue

I finally got it working again. I now open the smartobject between the 2 dialogs. Somehow the GUI does update then properly. I than use command to switch documents. I also delete the prior delete file to keep smaller when saving. I thought this part of the code would make the script run longer. But it actually faster then. Sometimes its about 1 sec faster running it with 6 designs.

It was quite weird actually, because at one point i already had it working. Then for extra check i saved the main template closed photoshop opened it again and then suddenly it would run. So this time i did save the script file into a new version from the point it was working and then started fine tuning. 

I notice that when functions are below in the script this can cause issues. Now i make sure the functions are earlier in the lines. Im not sure im 100% cirrect on this, but it seems this does influence the script sometimes.

Im also suspending the history, i believe this also speeds things up since they dont neet to be written to the log and the GUI.

Below version works, ive tested it multiple times now while opening and closing the main file and restarting Phososhop a couple times. It works just a bit nicer now then the other version i had yesterday, there i opened the smartobject from the start manually.
 
after i waited a day now it still wont allow me to post a comment here?!? Im trying this with a linked version of the script. I also had to reply to the first comment. I cant reply to your latest comment, it will refresh and nothing is posted. Therefor i tagged you using your name, that way im sure you are notified
JJMack
Community Expert
Community Expert
January 5, 2021

The problem is strange and does not always fail the same way.  The Problem seems to be related to some smart object layer and the way the are crated.  For example the only template I had where the smart object did open right away with 

 

 

 

 

		runMenuItem(stringIDToTypeID('placedLayerEditContents'));

 

 

 

 

was one I download from the web.  When I replicated the Template on my Windows machine it did open right away.  However, if I ran the same batch job sever time in a row occasionally the object would fail to open right away in the middle of a batch but  the code I added to wait for it to open or to add a open would  solve the problem most of the time. Waiting always seem to work however occasionally other problems would happen if I added the open command. Perhaps I open  and update the object  then the opened again open again and missed up my script because it was the processing the wrong document.

 

Now the Template you posted only one smart object layer needs to be updated  but the template has several smart object layers on  the top of the stack.  My mockup scripts are design to only update the top of the  layers stack smart object layers.  It is easy to convert  Mockup templates to be compatible with my scripts design.  So I modified your template.  I simply grouped all the layer above the Background into a group named Mockup. I the used Ctrl+J to dupe the smart object layer that needs to be updated and move the copy out of the mockup group to the top of the layer stack and I removed the masks changed opacity and fill to 0 and turn off its visibility. 

 

Right away the Smart Object fail to open but my script had not problem populating the template.   I then replicated  your template.  I saved the smart object work file as a PSD File.   I them placed the PSD file into the replicated template above the smart object layer that needs the replacement. and did a Ctrl+J to dupe it and moved the dupe to the top of the stack set fill and opacity  to 0 and turn off its visibility. and deleted the old top of the stack smart object layer..  I then  moved the vector layer mask off of the smart object layer  to the placed psd smart object layer and the deleted the smart object layer that needed to be replaced.  I clipped the Smart object layer to the Phone case layer at the sized the object with a transform to cover the phone case and Saved the Template.   On my machine this template object open right away. Running many batches occasionally it  may fails to open.    This is a strange problem.  I have not test in PS 2020 just 2021.

 

Here is a link to a zip file the has my text templates and scripts Mockups.zip 

JJMack
JJMack
Community Expert
Community Expert
January 5, 2021

I have now tested with CS6,  CC 2014, CC 2018, CC 2019, PS 2020 and PS 2021.  All seen to fail to open the Smart Object Layer's  object that your Mac created right away like the one I had downloaded.  Where in PS 2021 version 22.1 if I  wait using a wait till message the object will open.   In prior Photoshop the object never opens I have to add the open for the temp work file that was created by Photoshop for placeLeyerEditContents  but did not open.  

 

So the scripts in my toolkit work in Photoshop version prior to PS 2021 on windows machines.  I'm not positive they will on Mac for I'm not sure of where Photoshop created the temp work file on a mac.  This is what I use for Windows it may be the same for  Mac. depends on Forder.temp beint the place the file is created

 

 

var workFile = new File(Folder.temp + "/" +  name);  // May work for both Windows and Mac

 

 

 

PS 22.1 can occasionally have problem if I add the Open Command. However,  adding the open performs faster than waiting for the object to eventually open So I will not be changing my scripts for waiting requires human interaction which is not appropriate for a batch process.

 

I look at you script its seem to work on my machine but has issues with Place scaling images  and it  leave the object open.   I particularly do not like templates that have smart object  layer where the object is layered and to populate  the template you have to edits late within the object. Templates like that are too hard to use and  requite a custom script for automation.  It is far easier to create templates that simply need the smart object replaced.  So I simplified your Template or the one you purchased or downloaded.   I rasterized some layers  and moved the tool bar layers into the template from the object and added a camera layer.  This template can be batch processed with my script and if you use its edit option replacement images can be any size. The phone screen will be filled with image content.  If replacement images  are Phone size my scripts default isuse  Replace content not edit here the template. samsung-s20-mockup-xxx.psd 

 

http://www.mouseprints.net/old/dpr/samsung-s20-mockup-xxx.psd 

JJMack
JJMack
Community Expert
Community Expert
November 1, 2019

A PSD Object will open in Photoshop and your script will still be in cintrol of Photoshop and can edit the opened object. However, you need to be careful opening Smart Object Layers contents using A Photoshop script.  There are many ways smart object layers are created. All smart Object Layers's Object are not Photoshop Objects.  If you open them in a Photoshop script they will open in other applications or a Photoshop ACR Plug-in. The Photoshop script that opened the object  will lose control till the Application or pug-in execution finishes The script can not edit such objects.   R-bin posted code you can use to test the type object a smart object contains.  To determine if the object will open in Photoshop or not. I use that code in my Batch Photoshop Mockups scripts when the user want toe edit object rather than replace smart object layer object using replace content.   My scripts can not handle editing Mockup templates smart object layers that have none Photoshop object. Only replace content is supported  for none when Smart Object layer have none Photoshop Objects.

 

 

 

 


function objectIsPsObject(SOlayer) {
	//Thanks to r-bin
	var ext = smartobject_file_ext(SOlayer);  
    var rc = true;
	switch (ext)  
		{  
		case "nef":  
		case "cr2":  
		case "crw":  
		case "raf":  
		case "orf":  
		case "mrw":  
		case "dcr":  
		case "mos":  
		case "raw":  
		case "pef":  
		case "srf":  
		case "dng":  
		case "x3f":  
		case "erf":  
		case "sr2":  
		case "kdc":  
		case "mfw":  
		case "mef":  
		case "arw":  
		case "nrw":  
		case "rw2":  
		case "rwl":  
		case "iiq":  
		case "3fr":  
		case "fff":  
		case "srw":  
		case "ai":
		case "svg":
		case "pdf":
		case "esp":
			rc = false.	
			break;  
		case "error":  
			rc = false;
			break;         
  		default:  
			rc = true;
			break;  
    }  
	return rc;
}

 

 

 

 r-bin code 

JJMack
Stephen Marsh
Community Expert
Community Expert
November 1, 2019

JJMack, the code as posted does not work...

 

When I add:

 

objectIsPsObject();

 

An error is returned from your posted code:

 

Runtime Error: Error Code# 24: smartobject_file_ext is not a function on the following code entry:
 
var ext = smartobject_file_ext(SOlayer);
schroef
Inspiring
January 4, 2021

@JJMack 

 

thanks once more for taking the time to look at it. I also had the same idea what you did with the while loop, but its goes into never ending loop. The script simply runs to fast for the GUI to even do anything. I tried a couple variations like if doc lenght isnt 2 then rerun the same function. That also goes into this never ending loop and i need to escape running script and in some cases even need force end photoshop because i cant get the script to stop.

 

PS i forgot to mention it earlier, your open smartobject function also throws this error. There i something not correct in the code, perhaps its missing curly brackets. I do see these one line if states before and sometimes they work. However i think its "throw" which is causing this error. Is this perhaps because i use the extension JSX vs JS?!


 

Ive started a fresh new file with some test code in there to check if the editcontent works. PS it will always work if you an alert in there, somehow when i use that the GUI does update properly. But running file without will not run the script properly.

 

In this current state, your function throws a script error which we see in the image above.

 

The way i run this is have the mockup, so the PSD with the phone. I select the layer which is red (smartobject). I run the script, it will prompt you to select images, For a test i made those screen image in that zip file. Select one or a couple. It will then prompt for an export folder. For now ive turned of the save function since the main function doesnt even run properly. 

#target photoshop


var docRef = app.activeDocument;
var actLayer = docRef.activeLayer;


function cTID(s) {
    return app.charIDToTypeID(s);
};

function sTID(s) {
    return app.stringIDToTypeID(s);
};




////// open smart object //////
function openSmartObject(theLayer) {
    current = app.activeDocument;
    alert(theLayer)
    if (theLayer.kind == "LayerKind.SMARTOBJECT") {
        runMenuItem(stringIDToTypeID('placedLayerEditContents'));
        if (current == app.activeDocument) {
            try {
                var r = new ActionReference();
                r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("smartObject"));
                r.putIdentifier(stringIDToTypeID("layer"), theLayer.id);
                var name = executeActionGet(r).getObjectValue(stringIDToTypeID("smartObject")).getString(stringIDToTypeID("fileReference"));
            } catch (e) {
                throw theLayer + " Smart Object Did not Open";
            }
            var workFile = new File(Folder.temp + "/" + name); // May work for both Windows and Mac
            if (workFile.exists) app.open(File(workFile));
            if (current == app.activeDocument) throw theLayer + " Smart Object Did not Open";
        }
    } else {
        alert(theLayer +" is not a smartobject");
    }
    return app.activeDocument
};



// Check if object is PS
// R-Bin - JJ Mack
// https://community.adobe.com/t5/photoshop/extendscript-photoshop-edit-contents-smart-layer/m-p/10706542#M273949
function objectIsPsObject(SOlayer) {
	//Thanks to r-bin
	var ext = smartobject_file_ext(SOlayer);  
    var rc = true;
	switch (ext)  
		{  
		case "nef":  
		case "cr3":  
		case "cr2":  		
		case "crw":  
		case "raf":  
		case "orf":  
		case "mrw":  
		case "dcr":  
		case "mos":  
		case "raw":  
		case "pef":  
		case "srf":  
		case "dng":  
		case "x3f":  
		case "erf":  
		case "sr2":  
		case "kdc":  
		case "mfw":  
		case "mef":  
		case "arw":  
		case "nrw":  
		case "rw2":  
		case "rwl":  
		case "iiq":  
		case "3fr":  
		case "fff":  
		case "srw":  
		case "ai":
		case "svg":
		case "pdf":
		case "esp":
			rc = false;	
			break;  
		case "error":  
			rc = false;
			break;         
  		default:  
			rc = true;
			break;  
    }  
	return rc;
}
  
function smartobject_file_ext(layer) {  
    try {         
        var r = new ActionReference();     
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("smartObject"));  
        r.putIdentifier(stringIDToTypeID("layer"), layer.id);  
        var name = executeActionGet(r).getObjectValue(stringIDToTypeID("smartObject")).getString(stringIDToTypeID("fileReference"));         
         
        var n = name.lastIndexOf(".");  
        if (n < 0) return "";  
     
        return name.substr(n+1).toLowerCase();  
        }  
    catch (e) { return "error"; }  
}    


function placeImage(newFile){
    // app.refresh(); // doesnt work
    // app.redraw();// doesnt work
    // waitMoment();
    // $.sleep(500)
    
    // Switch document
    // var desc111 = new ActionDescriptor();
    //     var ref13 = new ActionReference();
    //     ref13.putOffset( cTID('Dcmn'), 1 );
    // desc111.putReference( cTID('null'), ref13 );
    // desc111.putInteger( cTID('DocI'), 344 );
    // executeAction( cTID('slct'), desc111, DialogModes.NO );
    
    // Place images
    // alert(newFile)
    var desc174 = new ActionDescriptor();
    desc174.putInteger( cTID('Idnt'), 885 );
    desc174.putPath( cTID('null'), new File(newFile));
     desc174.putBoolean( cTID('Lnkd'), true );
    desc174.putEnumerated( cTID('FTcs'), cTID('QCSt'), cTID('Qcsa') );
        var desc175 = new ActionDescriptor();
        desc175.putUnitDouble( cTID('Hrzn'), cTID('#Pxl'), 0.000000 );
        desc175.putUnitDouble( cTID('Vrtc'), cTID('#Pxl'), 0.000000 );
    desc174.putObject( cTID('Ofst'), cTID('Ofst'), desc175 );
    desc174.putUnitDouble( cTID('Wdth'), cTID('#Prc'), 234.782609 ); // i know the scale > this will make the image fit the SO file
    desc174.putUnitDouble( cTID('Hght'), cTID('#Prc'), 234.697509 ); // i know the scale > this will make the image fit the SO file
    executeAction( cTID('Plc '), desc174, DialogModes.NO );

}
function exportMockupDesigns() {
    // Get OS
    // fromt "_LastLogEntry.jsx"
    isWindows = function() {
        return $.os.match(/windows/i);
    };
    isMac = function() {
        return !isWindows();
    };
    var osPath = (isMac() ? '/' : "/"); // resolve windows vs osx paths
    // alert(isMac())


    if (app.documents.length > 0) {
        var myDocument = app.activeDocument;
        var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1];
        var thePath = myDocument.path;
        var theLayer = myDocument.activeLayer;
        // jpg options;
        var jpgopts = new JPEGSaveOptions();
        jpgopts.embedProfile = true;
        jpgopts.formatOptions = FormatOptions.STANDARDBASELINE;
        jpgopts.matte = MatteType.NONE;
        jpgopts.quality = 8;
        // check if layer is smart object;
        if (theLayer.kind != "LayerKind.SMARTOBJECT") {
            alert("selected layer is not a smart object")
        } else if (objectIsPsObject(actLayer) != true) {
            alert("The SmartOjbect is not a PSB or PSD file")
            return 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
        } else {
            // select files;
            if ($.os.search(/windows/i) != -1) {
                var theFiles = File.openDialog("please select files", "*.psd;*.tif;*.jpg;*.jpeg;", true)
            } else {
                var theFiles = File.openDialog("please select files", getFiles, true)
            };
            // select Folder;
            // var theFolder = Folder.selectDialog("select folder");
            if (theFiles) {
                // var theFiles = theFolder.getFiles(/\.(jpg|tif|eps|psd|png)$/i);
                // Select destination folder
                var destinationFolder = Folder.selectDialog("Please select a destination folder");
                // work through the array;
                for (var m = 0; m < theFiles.length; m++) {
                    // replace smart object;
                    openSmartObject(theLayer);
                    // app.refresh()
                    // alert(editSO)
                    // waitMoment()
                    //  $.sleep(500)
                    // waitForRedraw();// notworking
                    placeImage(theFiles[m]);


                   // var theNewName = theFiles[m].name.match(/(.*)\.[^\.]+$/)[1];
                    //save jpg;
                   // myDocument.saveAs((new File(destinationFolder.toString() + "/" + theName + "_" + theNewName + ".jpg")), jpgopts, true);

                    // }
                }
            };
        }
    };

    ////// get psds, tifs and jpgs from files //////
    function getFiles(theFile) {
        if (theFile.name.match(/\.(psd|tif|png|jpg|jpeg)$/i) != null || theFile.constructor.name == "Folder") {
            return true
        };
    };
};
exportMockupDesigns();

 

 


This is the line causing that error 

 

 

if (current == app.activeDocument) throw theLayer + " Smart Object Did not Open";

 

 

 

Changing the file to .js vs .jsx doesnt help, it still returns that error. Its asif it doesnt understand throw statement.

 

On inspecting the throw error. I think your using it wrong, i you look at this example. Throw needs to be used with try and catch. Like you did a bit up in the function.

 

 

I dont think the try and catch make is very useful, its just adds more lines of code. Simply using if and then alert is about the same right?


i corrected the code and now the script does run. But it opens the wrong file.

 

Now with fuction working properly nothing is actually opened. As a check i added alert to see what layer is selected, however nothing is happening. I believe your function should alert if the smartobject cant be opened but it doesnt do that

////// open smart object //////
function openSmartObject(theLayer) {
    current = app.activeDocument;
    alert(theLayer)
    if (theLayer.kind == "LayerKind.SMARTOBJECT") {
        runMenuItem(stringIDToTypeID('placedLayerEditContents'));
        if (current == app.activeDocument) {
            try {
                var r = new ActionReference();
                r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("smartObject"));
                r.putIdentifier(stringIDToTypeID("layer"), theLayer.id);
                var name = executeActionGet(r).getObjectValue(stringIDToTypeID("smartObject")).getString(stringIDToTypeID("fileReference"));
            } catch (e) {
                throw theLayer + " Smart Object Did not Open";
            }
            var workFile = new File(Folder.temp + "/" + name); // May work for both Windows and Mac
            if (workFile.exists) app.open(File(workFile));
            try {
                if (current == app.activeDocument) {}
            } catch(e) {
                throw theLayer + " Smart Object Did not Open";
            }
        }
    } else {
        alert(theLayer +" is not a smartobject");
    }
    return app.activeDocument
};

  

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
October 31, 2019

One way:

 

app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));

 

https://community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/m-p/10644877

Participant
November 1, 2019

Thanks Stephen & JJmack, answer was right in front of me in the code but couldn't see it through the forest.