Skip to main content
groucho90
Known Participant
February 16, 2021
Question

Script to create new .psd with embedded raw file as smart object

  • February 16, 2021
  • 4 replies
  • 3486 views

I have a collection of camera raw files.  I would like to create a script that would embed each raw file as a smart object in a new .psd file with the same name as the original raw file.  I'd like to do this from Bridge.  I've done other photoshop scripting but don't see how to do this. 

This topic has been closed for replies.

4 replies

rob day
Community Expert
Community Expert
February 17, 2021

The regular API’s open() doesn’t seem to have an option to open as a smart object. The last script I posted was a quick translation of an AppleScript I use.

 

With JS there is the option to use ActionDescriptors to get at the smart object boolean—I just didn’t take the time to look at that. This seems to work with a simple open and save and is somewhat faster. The other options like color profile and bit depth are coming from your current Camera RAW prefs but they could be overridden in the open function:

 

 

 

#target photoshop

var f = Folder.selectDialog("Select the folder containing .CR2 Raw files"); 
if(f != null){ 
    fa = f.getFiles(/\.(CR2)$/i);
}


for (var i = 0; i < fa.length; i++){
    openAsSmart(fa[i])
    var d = app.activeDocument
    var n = d.name;
    //save in the same folder as a .PSD file
    var so = new PhotoshopSaveOptions({embedColorProfile:true, layers:true});
    var sPath = f + "/" + n + ".psd"
    d.saveAs(new File(sPath), so);
    d.close();

};   



/**
* Use ActionDescriptors to open RAW as a smart object
*  the file path 
*  void 
* 
*/
function openAsSmart(p){
    var d1 = new ActionDescriptor();
    d1.putPath( stringIDToTypeID( "null" ), new File( p ) );
    var d2 = new ActionDescriptor();
    d1.putObject( stringIDToTypeID( "as" ), stringIDToTypeID( "Adobe Camera Raw" ), d2 );
    d1.putBoolean( stringIDToTypeID( "smartObject" ), true );
    executeAction( stringIDToTypeID( "open" ), d1, DialogModes.NO );
}


 

 

 

 

JJMack
Community Expert
Community Expert
February 17, 2021

That will perform much better. 

 

With the Image Processor script the user can select which RAW file to process in the Bridge and where they want the PSD saved in the  Image Processor script dialog. The RAW files collection can come from many  folders. Additionally the user could include using an action they record to add additional editing steps to the PSD documents being created.

JJMack
rob day
Community Expert
Community Expert
February 17, 2021

But the Image Processor script also uses the API open(), and it is not opening the RAW files as smart objects when Open as Smart Object is checked as you are suggesting—unless something has changed with PS22. 

rob day
Community Expert
Community Expert
February 16, 2021

Sorry, I thought the active layer bounds was returning the original RAW pixel dimensions, but it’s not. I think this works:

 

#target photoshop

var f = Folder.selectDialog("Select the folder containing .CR2 Raw files"); 
if(f != null){ 
    fa = f.getFiles(/\.(CR2)$/i);
}


for (var i = 0; i < fa.length; i++){
    
    app.preferences.rulerUnits = Units.PIXELS
    var of = open (fa[i]);
    var w = of.width;
    var h = of.height;
    of.close(SaveOptions.DONOTSAVECHANGES);
    
    //a new 8-bit document with AdobeRGB as the profile assignment
    var d = app.documents.add(w, h, 300.0);
    d.mode = DocumentMode.RGB;
    d.bitsPerChannel = BitsPerChannelType.EIGHT
    d.colorProfileName = "Adobe RGB (1998)";
    
    //place the CR2
    placePS(fa[i], true);
    
    //get the layer name for the save
    var n = d.layers[0].name;
    
    //remove the backgound layer
    d.layers[1].remove();
    
    //save in the same folder as a .PSD file
    var so = new PhotoshopSaveOptions({embedColorProfile:true, layers:true});
    var sPath = f + "/" + n + ".psd"
    d.saveAs(new File(sPath), so);
    d.close();

};   



/**
* Place action
* @9397041 file path to place 
* @Return void 
* 
*/
function placePS(p){
    function cTID(s) { return app.charIDToTypeID(s); };
    var placeAction = new ActionDescriptor();
    placeAction.putPath( cTID('null'), new File(p));
    placeAction.putEnumerated( cTID('FTcs'), cTID('QCSt'), cTID('Qcsa') );
    executeAction( cTID('Plc '), placeAction, DialogModes.NO );
}


 

groucho90
groucho90Author
Known Participant
February 16, 2021

Rob,  thanks much, this looks like it will do what I want.  I have done a lot of Javascript programming, but never programmed using the Photoshop API this way.  This will be my entry into that world.   I'll write if I have more questions.  

Stephen Marsh
Community Expert
Community Expert
February 16, 2021

For smaller batches of images, I would just select the files in Bridge, then CMD/CTRL + R to open into ACR. Then select all files in ACR and open as objects. A script would then step through the open docs and save/close to PSD. The advantage is that this leverages built-in features and only needs the save loop to be scripted. The disadvantage is that open all files at once will take more memory so would not be good for large batches.

JJMack
Community Expert
Community Expert
February 16, 2021

Either Image Processor scripts can do what that user want to do once they select the RAW Files in the Bridge and use Bridge menu Tools>Photoshop>Image Processor as long as the Users ACR  worflow preferences is set to open as smart objects.  They can also set workflow preferences Color space and color bit depth.   If the user has set ACR setting for RAW files in sidecar files or ACR database they will be used, They could have Image processor open the First RAW file into ACR UI so the user can set conversion setting. Then the script will use those settings for converting all the RAW files selected. Or The user can have ACR use the Users  Default ACR settings for RAW file without current ACR conversion settings.  There is no need to save each open PSD manually or write a script to save the open document in Photoshop as PSD files in some location and colse all the open documents. With the Image Processor scripts they will only be working  one Document at at time.  If the were document open in Photoshop they will still be open in photoshop and untouched by the processing done. Not save and closed some scripted loop.

JJMack
Stephen Marsh
Community Expert
Community Expert
February 19, 2021

There is no need to save each open PSD manually or write a script to save the open document in Photoshop as PSD files in some location and colse all the open documents.


By @JJMack

 

I was simply noting another valid, even if less efficient approach to the issue.

JJMack
Community Expert
Community Expert
February 16, 2021

Bridge menu  Tools>Photshop>Image Processor...  Youe ACR Preferences woul neet to be onem as Object.  If Image Processor doe not crerate Smart Object Layers.  try Tools>Photoshop>Batch... make sure your ACR preferences is set to open object. ACR Process RAW files Photoshop does not.

JJMack
groucho90
groucho90Author
Known Participant
February 16, 2021

Not sure this is what I am after .. I already use the batch processor on collections of files to open them, do some work, and then write the result to a new file of a different type.  I'd like to do the same with the raw files, open each one in turn, embed it in a new document and then write the new document as .psd.   [Understand that PS does not process raw files, but when raw file is embedded as Smart Object ACR can be opened on the Smart Object layer.]

rob day
Community Expert
Community Expert
February 16, 2021

Try this Javascript, asks for a folder containing .CR2 files, places the in RAW file a new 8-bit .PSD with AdobeRGB assigned and saves back to the same directory:

 

 

 

 

#target photoshop


var f = Folder.selectDialog("Select the folder containing .CR2 Raw files"); 
if(f != null){ 
    fa = f.getFiles(/\.(CR2)$/i);
}


for (var i = 0; i < fa.length; i++){
    
    //a new 8-bit document with AdobeRGB as the profile assignment
    var d = app.documents.add();
    d.mode = DocumentMode.RGB;
    d.bitsPerChannel = BitsPerChannelType.EIGHT
    d.colorProfileName = "Adobe RGB (1998)";
    
    //place the CR2
    placePS(fa[i], true);
    
    //get the width and height of the CR2 layer and size the canvas to match
    var al = d.activeLayer.bounds;
    var w = boundsAsNumbers(al)[2]-boundsAsNumbers(al)[0]
    var h = boundsAsNumbers(al)[3]-boundsAsNumbers(al)[1]
    d.resizeCanvas (w, h, AnchorPosition.MIDDLECENTER);
    
    //get the layer name for the save
    var n = d.layers[0].name;
    
    //remove the backgound layer
    d.layers[1].remove();
    
    //save in the same folder as a .PSD file
    var so = new PhotoshopSaveOptions({embedColorProfile:true, layers:true});
    var sPath = f + "/" + n + ".psd"
    d.saveAs(new File(sPath), so);
    d.close();

};   



/**
* Place action
* @9397041 file path to place 
* @Return void 
*/
function placePS(p){
    function cTID(s) { return app.charIDToTypeID(s); };
    var placeAction = new ActionDescriptor();
    placeAction.putPath( cTID('null'), new File(p));
    placeAction.putEnumerated( cTID('FTcs'), cTID('QCSt'), cTID('Qcsa') );
    executeAction( cTID('Plc '), placeAction, DialogModes.NO );
}


/**
* A layer’s bounds returns an array of strings with ruler unit. Converts to numbers 
* @Return an array of numbers 
* 
*/
function boundsAsNumbers(b){
    return [Number(b[0].toString().split(' ')[0]), Number(b[1].toString().split(' ')[0]), Number(b[2].toString().split(' ')[0]), Number(b[3].toString().split(' ')[0])]
}