Copy link to clipboard
Copied
I'm pretty new to scripting, and taking sort of a deep dive here. (For me at least!)
I've got a script that creates uniquely-named displacement map file, then applies the map with a Displace Smart Filter. So far so good.
What I'd really like to take advantage of though is CC2019's new "Embed File Data in Smart Object" feature. This feature prevents the 'Could not update smart object files because the file was not found' error common when moving files with displace filters applied to smart objects between different computers. This error forces the user to redo the Displace filter, and browse to the correct map file. I want to avoid making my client have to do that!
I've used r-bin's Script Event Listener to try and sus this out. It appears that the generated code stores displace data in "DspD". You'll see it in the second to last line of the code I've pasted below. (It's truncated from 30110090 to 10000.) I assume this data is some representation of the map file. I'm wondering if there's a clever way to get that data, store it, and use it in my script. I'll be batch processing many, many files and they'll each have a unique map to grab.
var d = new ActionDescriptor();
d.putInteger(stringIDToTypeID("horizontalScale"), 10);
d.putInteger(stringIDToTypeID("verticalScale"), 10);
d.putEnumerated(stringIDToTypeID("displacementMap"), stringIDToTypeID("displacementMap"), stringIDToTypeID("stretchToFit"));
d.putEnumerated(stringIDToTypeID("undefinedArea"), stringIDToTypeID("undefinedArea"), stringIDToTypeID("repeatEdgePixels"));
d.putPath(stringIDToTypeID("displaceFile"), new File("~/Desktop//DisplaceMap_1668.psd"));
d.putBoolean(charIDToTypeID("EmbF"), true);
d.putData(charIDToTypeID("DspD"), /* real data length = 30110090, truncated to 10000*/ String.fromCharCode(0x40,0x1A,0x00,0x00,0x80,....
executeAction(stringIDToTypeID("displace"), d, DialogModes.NO);
I made some changes to the script, as it failed when I restarted PS. I made it so that it got the path of the displacement smartobject layer and inserted that into the function that runs the displacement:
...#target photoshop
var doc = activeDocument;
var curLayer = doc.activeLayer;
var disMap = doc.layers.getByName('displace test');
doc.activeLayer = disMap;
editSO ();
var disDoc = activeDocument;
var disFile = disDoc.path +'/' + disDoc.name;
app.activeDocument = doc;
doc.activeLayer = curLayer;
editDis (dis
Copy link to clipboard
Copied
I don't have two computers to try this, so in theory, you should be able to embed the displacement map into your file. Would would then need to open that smart object, by double clicking on the layer icon. You could then use scriptListener to record making the displacement map, as in tnn e code that you have, or try and use that code, but you will need to change the path on both ways. Smart objects are opened in the temp file of that particular user, so you have to use the tilde symbol to point to the user's folder. So the following script will edit a smartObject with an embedded displacement map. Note in line 48 that I use the ~ to direct to the user's temp folder. In line 4 you need to name the SO layer that has your displacement map. In lines 36 and 38 are the values for displacement. You can put variables there and make a UI to replace them. Here is my screen shot of my setup:
#target photoshop
var doc = activeDocument;
var curLayer = doc.activeLayer;
var disMap = doc.layers.getByName('displace test');
editSO ();
var disDoc = activeDocument;
app.activeDocument = doc;
doc.activeLayer = curLayer;
editDis ();
function editSO(){
var idplacedLayerEditContents = stringIDToTypeID( "placedLayerEditContents" );
var desc3 = new ActionDescriptor();
executeAction( idplacedLayerEditContents, desc3, DialogModes.NO );
}
editDis ()
function editDis(){
var idsetd = charIDToTypeID( "setd" );
var desc9 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idfilterFX = stringIDToTypeID( "filterFX" );
ref3.putIndex( idfilterFX, 1 );
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref3.putEnumerated( idLyr, idOrdn, idTrgt );
desc9.putReference( idnull, ref3 );
var idfilterFX = stringIDToTypeID( "filterFX" );
var desc10 = new ActionDescriptor();
var idFltr = charIDToTypeID( "Fltr" );
var desc11 = new ActionDescriptor();
var idHrzS = charIDToTypeID( "HrzS" );
desc11.putInteger( idHrzS, 10 );
var idVrtS = charIDToTypeID( "VrtS" );
desc11.putInteger( idVrtS, 10 );
var idDspM = charIDToTypeID( "DspM" );
var idDspM = charIDToTypeID( "DspM" );
var idStrF = charIDToTypeID( "StrF" );
desc11.putEnumerated( idDspM, idDspM, idStrF );
var idUndA = charIDToTypeID( "UndA" );
var idUndA = charIDToTypeID( "UndA" );
var idRptE = charIDToTypeID( "RptE" );
desc11.putEnumerated( idUndA, idUndA, idRptE );
var idDspF = charIDToTypeID( "DspF" );
desc11.putPath( idDspF, new File( "~/AppData/Local/Temp/displace test1.psd" ) );
var idEmbF = charIDToTypeID( "EmbF" );
desc11.putBoolean( idEmbF, true );
var idDspD = charIDToTypeID( "DspD" );
var idDspl = charIDToTypeID( "Dspl" );
desc10.putObject( idFltr, idDspl, desc11 );
var idfilterFX = stringIDToTypeID( "filterFX" );
desc9.putObject( idfilterFX, idfilterFX, desc10 );
executeAction( idsetd, desc9, DialogModes.NO );
}
Here's after I run my script. Note that the a the SO displacement file has been opened.
Copy link to clipboard
Copied
I made some changes to the script, as it failed when I restarted PS. I made it so that it got the path of the displacement smartobject layer and inserted that into the function that runs the displacement:
#target photoshop
var doc = activeDocument;
var curLayer = doc.activeLayer;
var disMap = doc.layers.getByName('displace test');
doc.activeLayer = disMap;
editSO ();
var disDoc = activeDocument;
var disFile = disDoc.path +'/' + disDoc.name;
app.activeDocument = doc;
doc.activeLayer = curLayer;
editDis (disFile)
function editSO(){
var idplacedLayerEditContents = stringIDToTypeID( "placedLayerEditContents" );
var desc3 = new ActionDescriptor();
executeAction( idplacedLayerEditContents, desc3, DialogModes.NO );
}
function editDis(dMapFile){
var idsetd = charIDToTypeID( "setd" );
var desc9 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idfilterFX = stringIDToTypeID( "filterFX" );
ref3.putIndex( idfilterFX, 1 );
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref3.putEnumerated( idLyr, idOrdn, idTrgt );
desc9.putReference( idnull, ref3 );
var idfilterFX = stringIDToTypeID( "filterFX" );
var desc10 = new ActionDescriptor();
var idFltr = charIDToTypeID( "Fltr" );
var desc11 = new ActionDescriptor();
var idHrzS = charIDToTypeID( "HrzS" );
desc11.putInteger( idHrzS, 40 );
var idVrtS = charIDToTypeID( "VrtS" );
desc11.putInteger( idVrtS, 40 );
var idDspM = charIDToTypeID( "DspM" );
var idDspM = charIDToTypeID( "DspM" );
var idStrF = charIDToTypeID( "StrF" );
desc11.putEnumerated( idDspM, idDspM, idStrF );
var idUndA = charIDToTypeID( "UndA" );
var idUndA = charIDToTypeID( "UndA" );
var idRptE = charIDToTypeID( "RptE" );
desc11.putEnumerated( idUndA, idUndA, idRptE );
var idDspF = charIDToTypeID( "DspF" );
desc11.putPath( idDspF, new File( dMapFile ) );
var idEmbF = charIDToTypeID( "EmbF" );
desc11.putBoolean( idEmbF, true );
var idDspD = charIDToTypeID( "DspD" );
var idDspl = charIDToTypeID( "Dspl" );
desc10.putObject( idFltr, idDspl, desc11 );
var idfilterFX = stringIDToTypeID( "filterFX" );
desc9.putObject( idfilterFX, idfilterFX, desc10 );
executeAction( idsetd, desc9, DialogModes.NO );
}
Copy link to clipboard
Copied
Hello Chuck,
As I understand, the script should create a displacement map from a layer named "displace test" that represents the reference map for the image that is above as in your example but I am getting the following error 8800 whenever I load the script:
The object "filter effects 1 of current layer" is not currently available.
Here is an image to see what I have done so far:
Thank you,
Damian
Copy link to clipboard
Copied
That is because of some filterfx mentioned in the script. Seems to be some add-in or plug in.
Copy link to clipboard
Copied
I think this doesn't work for PS2022? That would be very helpful if anyone can share the compatible one with the latest ps.