Created
July 21, 2025 13:54
-
-
Save stephenjwatkins/41a2547d4a249527692550bc4096afd6 to your computer and use it in GitHub Desktop.
Photoshop script to replace a Smart Object within a PSD using "Place Embedded" with specified image and saves result as a JPG. Preserves transformations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Photoshop script to replace a Smart Object within a PSD using "Place Embedded" with specified image and saves result as a JPG. Preserves transformations. | |
| // 2025. Use at your own risk | |
| // Can be run in an automated fashion on Mac via AppleScript: | |
| // osascript -e "tell application \"Adobe Photoshop 2025\" to activate do javascript of file \"replace_smartobject_psd_placeembedded.jsx\"" | |
| #target photoshop | |
| var mockupFilePath = "~/mockup.psd"; | |
| var designFilePath = "~/design.png"; | |
| var exportFilePath = "~/export.jpg"; | |
| var jpegOptions = new JPEGSaveOptions(); | |
| jpegOptions.quality = 9; | |
| jpegOptions.embedColorProfile = true; | |
| jpegOptions.matte = MatteType.NONE; | |
| app.open(new File(mockupFilePath)); | |
| var myDocument = app.activeDocument; | |
| var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1]; | |
| var thePath = myDocument.path; | |
| var smartObject = findSmartObject(app.activeDocument); | |
| var theLayer = smartObject; | |
| myDocument.activeLayer = theLayer; | |
| if (theLayer.kind != "LayerKind.SMARTOBJECT") { | |
| alert("selected layer is not a smart object"); | |
| } else { | |
| theLayer = editSmartObjectAndPlaceEmbedded(designFilePath, theLayer); | |
| myDocument.saveAs(new File(exportFilePath), jpegOptions, true); | |
| app.activeDocument.close(SaveOptions.DONOTSAVECHANGES); | |
| } | |
| function findSmartObject(doc) { | |
| try { | |
| // Find all smart objects in the document | |
| var smartObjects = findSmartObjects(doc); | |
| if (smartObjects.length === 0) { | |
| alert("No smart objects found in the document."); | |
| return; | |
| } | |
| // If multiple smart objects exist, let user choose which one to replace | |
| var targetSmartObject; | |
| if (smartObjects.length === 1) { | |
| targetSmartObject = smartObjects[0]; | |
| } else { | |
| // For multiple smart objects, select the first one | |
| // You can modify this logic to let user choose specific smart object | |
| targetSmartObject = smartObjects[0]; | |
| alert("Multiple smart objects found. Using the first one."); | |
| } | |
| return targetSmartObject; | |
| } catch (error) { | |
| throw new Error("Failed to replace smart object content: " + error.message); | |
| } | |
| } | |
| function findSmartObjects(doc) { | |
| var smartObjects = []; | |
| try { | |
| // Search through all layers recursively | |
| function searchLayers(layers) { | |
| for (var i = 0; i < layers.length; i++) { | |
| var layer = layers[i]; | |
| // Check if layer is a smart object | |
| if (layer.kind === LayerKind.SMARTOBJECT) { | |
| smartObjects.push(layer); | |
| } | |
| // If layer is a group, search its layers | |
| if (layer.typename === "LayerSet") { | |
| searchLayers(layer.layers); | |
| } | |
| } | |
| } | |
| searchLayers(doc.layers); | |
| } catch (error) { | |
| throw new Error("Error searching for smart objects: " + error.message); | |
| } | |
| return smartObjects; | |
| } | |
| function editSmartObjectAndPlaceEmbedded(newFile, smartObjectLayer) { | |
| try { | |
| // Store reference to the main document | |
| var mainDocument = app.activeDocument; | |
| // Edit the smart object contents using ActionDescriptor | |
| editSmartObjectContents(smartObjectLayer); | |
| // Now we're inside the smart object document | |
| var smartObjectDoc = app.activeDocument; | |
| // Clear existing content (optional - you can modify this based on your needs) | |
| // smartObjectDoc.layers[0].delete(); | |
| // Place the new file as embedded | |
| placeEmbedded(newFile); | |
| // Save changes to the smart object | |
| smartObjectDoc.save(); | |
| // Close the smart object document and return to main document | |
| smartObjectDoc.close(SaveOptions.SAVECHANGES); | |
| // Return to the main document | |
| app.activeDocument = mainDocument; | |
| return smartObjectLayer; | |
| } catch (error) { | |
| alert("Error editing smart object: " + error.message); | |
| // Try to return to main document if there was an error | |
| try { | |
| app.activeDocument = mainDocument; | |
| } catch (e) { | |
| // If we can't return to main document, try to close any open smart object | |
| if (app.documents.length > 1) { | |
| app.activeDocument.close(SaveOptions.DONOTSAVECHANGES); | |
| } | |
| } | |
| throw error; | |
| } | |
| } | |
| function placeEmbedded(filePath) { | |
| var actDesc = new ActionDescriptor(); | |
| actDesc.putPath(charIDToTypeID("null"), new File(filePath)); | |
| actDesc.putEnumerated( | |
| charIDToTypeID("FTcs"), | |
| charIDToTypeID("QCSt"), | |
| charIDToTypeID("Qcsa") | |
| ); | |
| executeAction(charIDToTypeID("Plc "), actDesc, DialogModes.NO); | |
| } | |
| function editSmartObjectContents(smartObjectLayer) { | |
| try { | |
| // Make the smart object layer active | |
| app.activeDocument.activeLayer = smartObjectLayer; | |
| // Use ActionDescriptor to edit smart object contents | |
| var desc = new ActionDescriptor(); | |
| var ref = new ActionReference(); | |
| ref.putEnumerated( | |
| charIDToTypeID("Lyr "), | |
| charIDToTypeID("Ordn"), | |
| charIDToTypeID("Trgt") | |
| ); | |
| desc.putReference(charIDToTypeID("null"), ref); | |
| desc.putEnumerated( | |
| charIDToTypeID("Usng"), | |
| charIDToTypeID("Plc "), | |
| charIDToTypeID("Plc ") | |
| ); | |
| executeAction( | |
| stringIDToTypeID("placedLayerEditContents"), | |
| desc, | |
| DialogModes.NO | |
| ); | |
| } catch (error) { | |
| throw new Error("Failed to edit smart object contents: " + error.message); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment