Skip to content

Instantly share code, notes, and snippets.

@laryn
Last active May 28, 2024 15:53
Show Gist options
  • Save laryn/0a1f6bf0dab5b713395a835f9bfa805c to your computer and use it in GitHub Desktop.
Save laryn/0a1f6bf0dab5b713395a835f9bfa805c to your computer and use it in GitHub Desktop.
Photoshop script to replace a smart object within a PSD with selected image(s) and save result as a JPG. (Transformations to the smart object will be applied to new images).
// Replace SmartObject’s Content and Save as JPG
// 2017, use it at your own risk
// Via @Circle B: https://graphicdesign.stackexchange.com/questions/92796/replacing-a-smart-object-in-bulk-with-photoshops-variable-data-or-scripts/93359
// JPG code from here: https://forums.adobe.com/thread/737789
#target photoshop
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;
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 8;
// Check if layer is SmartObject;
if (theLayer.kind != "LayerKind.SMARTOBJECT") {
alert("selected layer is not a smart object")
} else {
// Select Files;
if ($.os.search(/windows/i) != -1) {
var theFiles = File.openDialog("please select files", "*.psd;*.tif;*.jpg", true)
} else {
var theFiles = File.openDialog("please select files", getFiles, true)
};
if (theFiles) {
for (var m = 0; m < theFiles.length; m++) {
// Replace SmartObject
theLayer = replaceContents(theFiles[m], theLayer);
var theNewName = theFiles[m].name.match(/(.*)\.[^\.]+$/)[1];
// Save JPG. If you have need of saving different artboards into separate files,
// see https://gist.github.com/laryn/0a1f6bf0dab5b713395a835f9bfa805c#gistcomment-3996733
myDocument.saveAs((new File(thePath + "/" + theName + "_" + theNewName + ".jpg")), jpgSaveOptions, true,Extension.LOWERCASE);
}
}
}
};
// Get PSDs, TIFs and JPGs from files
function getFiles(theFile) {
if (theFile.name.match(/\.(psd|tif|jpg)$/i) != null || theFile.constructor.name == "Folder") {
return true
};
};
// Replace SmartObject Contents
function replaceContents(newFile, theSO) {
app.activeDocument.activeLayer = theSO;
// =======================================================
var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc3.putPath(idnull, new File(newFile));
var idPgNm = charIDToTypeID("PgNm");
desc3.putInteger(idPgNm, 1);
executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);
return app.activeDocument.activeLayer
};
@magicsun
Copy link

magicsun commented Oct 11, 2022

@magicsun

It's been a long time i used this script, i believe i read earlier there were are some errors in the initial script.

I'll need to check own version again and see what causing this. The error shown, i due to something in the script getting "stuck". Its trying to do something which it can't at that point. It could also be due to different version of Photoshop.

Bit it would help me more if i could get a sample file and some test images your trying to run.

I tried to look at your script using my phone, it's k nada weird and hard to read. I'll have a look tomorrow when I wake up. See what happens.

@schroef Thank you that would be great. I'm unable to upload psd or zip so i've uploaded files to wetransfer to download:
https://we.tl/t-ZfKQFmVoO8

Regards,
Mirna

@schroef
Copy link

schroef commented Oct 13, 2022

@magicsun

Sorry for the late reply. But the issue with the error is that The script starts with checking if active layer is a smartObject, then the function "loadLayerMaskSelection". But this function needs a layer with a mask. But in your file that is the layerset above the smartObject layer. I dont see any code where it travels up in the layer hierarchy.

If you always use this same document setup. You can simply use a command to travel up the stack, copy that code from scriptListener and add that. Otherwise add a layer name to the set and use a function to get layer by name to make it active. Then move back to the smartObject layer. The command is myDocument.activeLayer = myDocument.layers.getByName("ADDYOURLAYERNAMEHERE");

Ive renamed some of the layers in your doc, sorry i work very organized in PS. But this also allows you to get layer names properly and which is more descriptive. Ive adjusted the script and now it works i think it shou;d. Ive added a WeTransfer with 2 example outputs i got with the adjusted script. So you need to have the image placed in the folder according to the size of the mask. So they will keep that wooden borden then when exported, is that correct?

What is important is that you start the document with the RED layer selected. You can always add the command i also added, to make sure it will go to that layer. See above how to make a layer active by using layer name.

PS do you have a link to that xbytors stdlib Seems they have some nice tools
EDIT sorry i actually know these tools. Have taken some parts of those marvelous scripts as well. that stdLib is very usefull!!

https://we.tl/t-PYXWuiBN6G

00-test_package2

@magicsun
Copy link

@schroef I'm so sorry. Due to deadlines I couldn't check back earlier and now I see that the transfer link has expired.
I'm sorry .. are you able to make a new link? if not that's OK too, It's my fault I did not download earlier.

Thank you for the clear explanation. I've used the script on this page, which works OK, but smaller labels don't get resized to fit the height. I've then combined two scripts together, but i'm not programmer so I basically try with trial and error.

I'm going to look into the directions you have given in your reply. Thank you :)

Regards,
Mirna

@schroef
Copy link

schroef commented Oct 29, 2022

@magicsun
No worries Mirna, I'll try to make a new link later today. I'm also no developer but i really like fiddling around with code. Trial and error and google gets you a very long way. So does years of community posts as well.

@schroef
Copy link

schroef commented Oct 30, 2022

@magicsun
Here is a new link which should be valid for ever. The site is legit, not sure if you get warnings. Ive used this for couple years now if i need long lasting links
https://filedropper.com/d/s/zlAHpI3OpHnxhmTcUKz4fiI7ut7lV8

@mrgdizzle
Copy link

Hi,

The script is great I was wondering if its possible to for the image loaded into the smart object to automatically scale to fit the smart object area?

@schroef
Copy link

schroef commented Mar 21, 2023

@mrgdizzle
Check the version in my post above yours. I adjusted it if someone earlier

@mrgdizzle
Copy link

Great thanks in the end I just amended the smart object size.
One more thing is it possible to batch edit 3D layer content in this way and save the files?
I have seen someone doing it with a script on youtube.

I'm not sure how to do it though

@schroef
Copy link

schroef commented Mar 24, 2023

@mrgdizzle
I honestly don't know. I have not worked that much with 3d files inside Photoshop, i find it sluggish and slow. Rather do that in dedicated 3d apps. Way better control and render engines.

I'm not sure that part is exposed to extendscript, honestly never have seen code related to that. But I've never search for it

EDIT
I did a quick peek with scriptlistner. Seems it is exposed. Not sure how you would tackle this, because when you import meshes you need to do a lot of work most times to get it somewhat representable nicely.

I did a quick check with "replace mesh", i see the code exposed. This means you could batch edit it. But i dont know if everything is exposed. When i checked the 3d items in the object, i dont see selecting parts shows code. But when i changed a color, something did show. However, if you need to script this as well, im not sure you would be able to. The mesh names all need to be the same in order to get this working. That almost impossible i think

// =======================================================
var idreplaceMesh = stringIDToTypeID( "replaceMesh" );
    var desc125 = new ActionDescriptor();
    var idkeythreeDObjectFileList = stringIDToTypeID( "key3DObjectFileList" );
        var list82 = new ActionList();
        list82.putPath( new File( "/Users/macpro1/Downloads/3d Presentaties Renders/Models/Banners/Roll-Up Banner_86x206/Banner206x86cm.obj" ) );
    desc125.putList( idkeythreeDObjectFileList, list82 );
    var idkeythreeDNameList = stringIDToTypeID( "key3DNameList" );
        var list83 = new ActionList();
        list83.putString( """VinyilDoek250x220_v3_Mar2013 Scene Replacement""" );
    desc125.putList( idkeythreeDNameList, list83 );
    var idkeythreeDObjectTypeList = stringIDToTypeID( "key3DObjectTypeList" );
        var list84 = new ActionList();
        list84.putInteger( 2 );
    desc125.putList( idkeythreeDObjectTypeList, list84 );
executeAction( idreplaceMesh, desc125, DialogModes.NO );

Also i dont see how we can replace the entire 3dlayer. I need to go into the 3d panel and then select a mesh part. Thus this wont allow us to replace objects. What you could try is simply place an object, then say render and then delete layer and than add a new layer.
Lots of items i did when adding a new 3d layer are not exposed to extendscript. However, the part add 3dlayer seems to be exposed. This could mean you could sort of do batch work with it. I dont know enough about 3d in photoshop. Not sure what you are trying to do

// =======================================================
var idaddthreeDLayerFromFile = stringIDToTypeID( "add3DLayerFromFile" );
    var desc237 = new ActionDescriptor();
    var idfileList = stringIDToTypeID( "fileList" );
        var list131 = new ActionList();
        list131.putPath( new File( "/Users/macpro1/Downloads/3d Presentaties Renders/Models/Banners/Roll-Up Banner_86x206/Banner206x86cm.obj" ) );
    desc237.putList( idfileList, list131 );
executeAction( idaddthreeDLayerFromFile, desc237, DialogModes.NO );

Here's a simple function i made for place 3d objects. I would need to invest some more time to make the layer hide/show or delete with each new item you want to use.

var fileToPlace = "/Users/macpro1/Downloads/3d Presentaties Renders/Models/BILLBOARDS/Billboard500x250/MODELS/EXPORTS/Halogeen_spot.obj"
// var fileToPlace = "/Users/macpro1/Downloads/3d Presentaties Renders/Models/Banners/Roll-Up Banner_86x206/Banner206x86cm.obj"
function placeFile(fileToPlace){
    // =======================================================
    var idaddthreeDLayerFromFile = stringIDToTypeID( "add3DLayerFromFile" );
        var desc237 = new ActionDescriptor();
        var idfileList = stringIDToTypeID( "fileList" );
            var list131 = new ActionList();
            list131.putPath( new File( fileToPlace ) );
        desc237.putList( idfileList, list131 );
    executeAction( idaddthreeDLayerFromFile, desc237, DialogModes.NO );
}

placeFile(fileToPlace)

The variable fileToPlace is simply the test OBJ i used. You can call this function from a loop. So if we use a dialog to get a list of 3d objects. We then call this function to place the object as a 3d layer. Then you do your work, i guess you want to render 3d previews orso

@stahlsparre
Copy link

stahlsparre commented Apr 21, 2023

Getting a wierd problem when using this script. The placed JPG's in the smartobject become super zoomed in. Looking at the smartobject transform after processing, it seems it's been scaled up a lot.

My JPGs and smartobject canvas size are 1264px x 1895px
bild
bild
bild

The output smartobjects turn into 5263px x 7896px. This makes the output images truly zoomed in. (I get the same result if I rightclick the smartobject-layer and replace contents.)

bild
bild

If I click the Reset Transform button manually it snaps into the correct place:
bild
bild
bild

Any ideas why this is happening? This script is great but I don't get why it transforms the smartobject.

@laryn
Copy link
Author

laryn commented Apr 21, 2023

Just a quick guess but does the dpi match between the destination and the smart object?

@schroef
Copy link

schroef commented Apr 24, 2023

@stahlsparre
If you check the last nk i added to the file dropper website couple comments back. You'll find an update version of this script. This will adjust the new added image to match the correct size.

You new image has a bigger resolution than when that smart object initially was created

See this post how the new version works
https://gist.github.com/laryn/0a1f6bf0dab5b713395a835f9bfa805c?permalink_comment_id=4334299#gistcomment-4334299
That WeTransfer like NJ doesn't work anymore, a couple posts below is a file dropper link. That site is safe, chrome Warns of it but it's okay

@miguelalbert369
Copy link

miguelalbert369 commented Aug 15, 2023

@schroef

It seems like the FileDropper web server is down for a week or more now. Is there another link that you can post? Cheers

Screenshot 2023-08-15 220239

@schroef
Copy link

schroef commented Aug 22, 2023

@miguelalbert369

Ive added to my own github. > https://github.com/schroef/Photoshop-Scripts#replace-smartobject-image
I added it quickly so not much info. Make sure you have the same structure as i show in that image, especially the naming. If this doesnt match, the script will return errors
replace_smartobject_image-layers-naming-and-order

@amfie
Copy link

amfie commented Sep 29, 2023

How could I amend this to include linked smart objects nested within regular smart objects? Also is it possible to ignore smart objects with no link?

@schroef
Copy link

schroef commented Sep 29, 2023

@amfie

For nested smart objects inside a smartonbject it would need a extra loop and call the same function again.

What do you mean by smart objects without a link? Do you you mean those layers which are converted to smartobject and once being edited are a temp psb file?

@schroef
Copy link

schroef commented Sep 30, 2023 via email

@dbashbusiness
Copy link

Hi, I am new to using scripts and I tried this one, but for some reason it places image incorrectly, as if moves my original smart object. Any idea what I am setting up incorrectly?
Untitled

here's link to example psd file https://drive.google.com/drive/folders/1JSJu0UH32buuP6Kh7b0x9dkpTOBmQpGU?usp=sharing

@schroef
Copy link

schroef commented Oct 12, 2023

@dbashbusiness
I just tried it and it works fine for me with the send link. PS is it perhaps you used a different image. I see a image with green leaves and not pink leaves.

Have you tried this version?
https://github.com/schroef/Photoshop-Scripts#replace-smartobject-image

EDIT
okay after checking one time more. I noticed this seems to be happening because your initial smartobject is skewed or transformed into perspective. Once i test it using a not deformed image it looks better. But still doesnt fit properly because the mask is skewed. Perhaps it would need more work. Im not sure if we can also apply proper skewing or perspective transformation using script.

using not skewed smartobject

@dbashbusiness
Copy link

Hi,
I am trying a different approach :D
Here's a different mockup I downloaded. I tried adjusting the layers to match your requirements - changed names on smart object and existing mask layer, ungrouped the folder.
However, now the image is too zoomed in. Is there something I do incorrectly with the layers? I am not quite sure how to create correct mask layer on smart object myself..
here's the original mockup as well as the one edited by me, if you would have time to review.

THANK YOU!

https://drive.google.com/drive/folders/1Vf9VRgtPEw93HCdHoiRCTfCSNcAaltD_?usp=sharing

darkMockup_IMG_0837

IMG_0837

@schroef
Copy link

schroef commented Oct 12, 2023

Hi, I am trying a different approach :D Here's a different mockup I downloaded. I tried adjusting the layers to match your requirements - changed names on smart object and existing mask layer, ungrouped the folder. However, now the image is too zoomed in. Is there something I do incorrectly with the layers? I am not quite sure how to create correct mask layer on smart object myself.. here's the original mockup as well as the one edited by me, if you would have time to review.

THANK YOU!

https://drive.google.com/drive/folders/1Vf9VRgtPEw93HCdHoiRCTfCSNcAaltD_?usp=sharing

You need to use the exaxt same layer setup as i showed earlier. I wont work otherwise.
Screen Shot 2023-10-12 at 17 47 56
This is the correct order

layers naming and order

PS i found a different script and have altered it. That script now works on your earlier example and also does keep the correct perspective. Ill post a link tomorrow

@dbashbusiness
Copy link

Thank you so much! I will wait for the link.

Would you be able to guide me through creating your layers?
I'm not sure what exactly is done to get this masked layer.

@schroef
Copy link

schroef commented Nov 2, 2023

@dbashbusiness
Sorry for the long wait. Ill try to show you the workflow which is needed for this other version of the script.

Relink SmartObjects - v2

  1. Open the PSD file containing the artwork
  2. Selected linked SmartObject layer or place (link) a new SmartObject.
  3. Now convert this layer (SmartObject) again to a SmartObject. The earlier layer/SmartObject will become nested in the other. Name this layer "REPLACE DESIGN"
    You can copy this layer and move it to the top and set visibility OFF for easy access.
  4. Now apply your perspective transformation on the layer/smartobject in the main document.
  5. Optionally you can add a mask and transform the layer so its a bit bigger. This will fix the issue if a new linked image has a different ratio causing blank areas to appear. See images below for more clear explanation of why we want to do that.

I think im going to merge these 2 versions of the scripts into 1 main script. Then when with a dialog a user can pick either method. Thats way we can keep it as 1 script

This is the layer order you need to have now
layer-order-relinks-smartobject+perspective

Issue which shows when you relink images with different image ratio.
Fix-issues-Perspectivve-transofrmation-0

Add overlap to fix this issue
Fix-issues-Perspectivve-transofrmation-1

Relink SmartObjects keeping Perspective

@schroef
Copy link

schroef commented Dec 2, 2023

@milqnomadu have you already tried the version which I linked above?
They do exactly what you ask for, minus that prompt at the end. That's easy to add yourself. You can also very easily adjust the export settings to your need.

There are 2 versions now of this export file. One does not adjust the image of it's skewed or perspective transformer. However it will fit your images inside a mask. Proportions will matter depending on your mask. Meaning borders can appear showing the image below if a new linked image has different proportions vs the mash proportions.

The other version will linked images inside a transformed smartobject and will keep that transformation. That is something the original script here did not do.

@milqnomadu
Copy link

I have an issue with the code, I will link the detailed explaination because I cannot add images here:

https://stackoverflow.com/questions/77591593/photoshop-script-batch-smart-object-insert-replace-issues

@milqnomadu
Copy link

@schroef I tried the version above, however the output is the same I describe there. I don't really know how to cope with it.

@schroef
Copy link

schroef commented Dec 2, 2023

@milqnomadu
If you go to my GitHub link, I added it a couple posts above, it will show a layout in the layer panel. This is need to make it scale down the image to the mask dimensions. This will fix the issue I saw in that post you linked. I I understand correctly, your new linked image "design" is to big for the mockup, is that correct?

Edit
Here's the link to my repo
https://github.com/schroef/Photoshop-Scripts

Notice the layer panel and the order, this is very important for the resizing to work properly

@schroef
Copy link

schroef commented Jan 12, 2024

Ive been working on a new version of this script. After someone contacted me about a small issue with the current script. The original script did not resize the image. By adding the code from @magicsun and adding a mask, that work. But the image aspect ratio can cause an issue in that version. If the new images don't fit in terms of the image ratio, you would get blank spots. Ive also now have a version which replaces the content inside the linked SmartObject. This is a different approach and in some cases solves the issue.
I've also found a function on Adobe Community by Stephen A Marsh which allows the user to save as WebP.

I'm stilling testing out if this script can be one version or perhaps we keep both methods. Anyway, im working on adding a dialog window. The user can define settings and placement of the new image. This is for the version which edit the content of the SmartObject. The script also uses ObjectToDescriptor, this means when you reload the script it restores all last settings.

This is how it looks now, it already works with hard-coded save to WebP. Im now in the process of adding all other formats; BMP,JPG,PDF,PSD,TARGA,TIFF,WEBP,PNG-8,PNG-24.

dialog-design-v002

@shohidur333
Copy link

To replace a smart object within a PSD with selected image(s) and save the result as a JPG using a Photoshop script, you can refer to the detailed instructions provided in the article on BulkMockup. The article covers the use of scripts to automate the process and includes steps for replacing smart objects in bulk. The script mentioned in the article applies transformations to the smart objects and ensures that the changes are saved as JPG files.

@schroef
Copy link

schroef commented Jan 31, 2024

@shohidur333
My new versions actually does this, I've implemented 2 version now. One which edit the link itself, the other will edit the content inside the smartobject. The latter is slower however to the workflow need. But it's still a fraction of doing this all manually .

It's nice you have such expanded tutorials and writing. But it's a commercial product. $15 per month. Kinda steep price if you can get ir for free here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment