Skip to main content
Participating Frequently
February 10, 2018
Question

Batch replace smart objects in mockup file

  • February 10, 2018
  • 3 replies
  • 16981 views

Hi there,

I want to know if it's possible to import x-number of png images into a mockup template with a smart object and then all saved in jpgs? The following script is not working for me but it's probably close to what I need:

Batch replace smart objects

The script must do the following:

Search in folder for PNG files

Place the PNG image into the Smart Object (top center)

Save file as JPG into the source folder with the same name as the source file

For example:

Before the script

\Images\Image 1\PNG\Design1.png

\Images\Image 2\PNG\Design2.png

\Images\Image 3\PNG\Design3.png

\Images\Image 4\PNG\Design4.png

After the script

\Images\Image 1\PNG\Design1.png

\Images\Image 1\PNG\Mockup.jpg

\Images\Image 2\PNG\Design2.png

\Images\Image 2\PNG\Mockup.jpg

\Images\Image 3\PNG\Design3.png

\Images\Image 3\PNG\Mockup.jpg

\Images\Image 4\PNG\Design4.png

\Images\Image 4\PNG\Mockup.jpg

I hope this makes sense. I will appreciate if someone can give me an advise what is the best way to do that.

Kind regards,

Katt

This topic has been closed for replies.

3 replies

Participating Frequently
February 12, 2018

The script works fine for me but I have one issue here - I need the png placed in the top center of the Smart Object, so if the image is shorter it will be still on top.

c.pfaffenbichler
Community Expert
Community Expert
February 12, 2018

You can either include an additional Alignment step in the Script or try to change the line

layerY = ((docHeight*docRes/144) - (layerY+layerHeight/2));

to provide the result you want to achieve.

Participating Frequently
February 12, 2018

To be honest I have no idea how to do it. I don't know anything about scripting

c.pfaffenbichler
Community Expert
Community Expert
February 11, 2018

// place png files in selected smart object and save jpg;

// 2018, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

var basename = 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 = 10;

// check if layer is smart object;

if (theLayer.kind != "LayerKind.SMARTOBJECT") {alert ("selected layer is not a smart object")}

else {

// select files;

var theFolder = Folder.selectDialog ("select folder");

var theFiles = retrievePngFiles (theFolder, []);

if (theFiles) {

// work through the array;

for (var m = 0; m < theFiles.length; m++) {

var thePath = File(theFiles).path;

// open smart object;

var smartObject = openSmartObject (theLayer);

var theLayer2 = smartObject.activeLayer;

// place file and fit to convas;

var theNewOne = placeScaleRotateFile (theFiles, 0, 0, 100, 100, 0);

scaleLayerToFitCanvas ();

hideOthers ();

// close;

smartObject.close(SaveOptions.SAVECHANGES);

//save jpg;

myDocument.saveAs((new File(thePath+"/"+theFiles.name.match(/(.*)\.[^\.]+$/)[1]+"_"+basename+".jpg")),jpgopts,true);

// undo;

myDocument.activeHistoryState = myDocument.historyStates[myDocument.historyStates.length - 1];

}

}

}

};

////// get ong from subfolders //////

function retrievePngFiles (theFolder, theFiles) {

  if (!theFiles) {var theFiles = []};

  var theContent = theFolder.getFiles();

  for (var n = 0; n < theContent.length; n++) {

  var theObject = theContent;

  if (theObject.constructor.name == "Folder") {

  theFiles = retrievePngFiles(theObject, theFiles)

  };

  if (theObject.name.slice(-4).match(/\.(png)$/i) ) {

  theFiles.push(theObject)

  }

  };

  return theFiles

  };

////// place //////

function placeScaleRotateFile (file, xOffset, yOffset, theXScale, theYScale, theAngle) {

// =======================================================

var idPlc = charIDToTypeID( "Plc " );

    var desc5 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

    desc5.putPath( idnull, new File( file ) );

    var idFTcs = charIDToTypeID( "FTcs" );

    var idQCSt = charIDToTypeID( "QCSt" );

    var idQcsa = charIDToTypeID( "Qcsa" );

    desc5.putEnumerated( idFTcs, idQCSt, idQcsa );

    var idOfst = charIDToTypeID( "Ofst" );

        var desc6 = new ActionDescriptor();

        var idHrzn = charIDToTypeID( "Hrzn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc6.putUnitDouble( idHrzn, idPxl, xOffset );

        var idVrtc = charIDToTypeID( "Vrtc" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc6.putUnitDouble( idVrtc, idPxl, yOffset );

    var idOfst = charIDToTypeID( "Ofst" );

    desc5.putObject( idOfst, idOfst, desc6 );

    var idWdth = charIDToTypeID( "Wdth" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc5.putUnitDouble( idWdth, idPrc, theYScale );

    var idHght = charIDToTypeID( "Hght" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc5.putUnitDouble( idHght, idPrc, theXScale );

    var idAngl = charIDToTypeID( "Angl" );

    var idAng = charIDToTypeID( "#Ang" );

    desc5.putUnitDouble( idAngl, idAng,theAngle );

    var idLnkd = charIDToTypeID( "Lnkd" );

    desc5.putBoolean( idLnkd, true );

executeAction( idPlc, desc5, DialogModes.NO );

return app.activeDocument.activeLayer;

};

////// scale layer to fit canvas //////

function scaleLayerToFitCanvas () {

var ref = new ActionReference();

ref.putProperty (stringIDToTypeID ("property"), stringIDToTypeID ("bounds"));

ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var layerDesc = executeActionGet(ref);

var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));

var layerX = theBounds.getUnitDoubleValue(stringIDToTypeID("left"));

var layerY = theBounds.getUnitDoubleValue(stringIDToTypeID("top"));

var layerWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("right"))-layerX;

var layerHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))-layerY;

var ref1 = new ActionReference();

ref1.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var docDesc = executeActionGet(ref1);

var docWidth = docDesc.getUnitDoubleValue(stringIDToTypeID("width"));

var docHeight = docDesc.getUnitDoubleValue(stringIDToTypeID("height"));

var docRes = docDesc.getInteger(stringIDToTypeID("resolution"));

var scaleX = docWidth/layerWidth*docRes/72*100;

var scaleY = docHeight/layerHeight*docRes/72*100;

var theScale = Math.min(scaleX, scaleY);

layerX = ((docWidth*docRes/144) - (layerX+layerWidth/2));

layerY = ((docHeight*docRes/144) - (layerY+layerHeight/2));

// =======================================================

var idTrnf = charIDToTypeID( "Trnf" );

    var desc24 = new ActionDescriptor();

//    desc24.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcs0" ) );

    desc24.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );

    var idOfst = charIDToTypeID( "Ofst" );

        var desc25 = new ActionDescriptor();

        var idHrzn = charIDToTypeID( "Hrzn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc25.putUnitDouble( idHrzn, idPxl, layerX);

        var idVrtc = charIDToTypeID( "Vrtc" );

        desc25.putUnitDouble( idVrtc, idPxl, layerY);

    desc24.putObject( idOfst, idOfst, desc25 );

    var idWdth = charIDToTypeID( "Wdth" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc24.putUnitDouble( idWdth, idPrc, theScale );

    var idHght = charIDToTypeID( "Hght" );

    desc24.putUnitDouble( idHght, idPrc, theScale );

executeAction( idTrnf, desc24, DialogModes.NO );

};

////// open smart object //////

function openSmartObject (theLayer) {

if (theLayer.kind == "LayerKind.SMARTOBJECT") {

// =======================================================

var idplacedLayerEditContents = stringIDToTypeID( "placedLayerEditContents" );

    var desc2 = new ActionDescriptor();

executeAction( idplacedLayerEditContents, desc2, DialogModes.NO );

};

return app.activeDocument

};

////// hide others //////

function hideOthers () {

// hide others;

// =======================================================

var idShw = charIDToTypeID( "Shw " );

    var desc2 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var list1 = new ActionList();

            var ref1 = new ActionReference();

            var idLyr = charIDToTypeID( "Lyr " );

            var idOrdn = charIDToTypeID( "Ordn" );

            var idTrgt = charIDToTypeID( "Trgt" );

            ref1.putEnumerated( idLyr, idOrdn, idTrgt );

        list1.putReference( ref1 );

    desc2.putList( idnull, list1 );

    var idTglO = charIDToTypeID( "TglO" );

    desc2.putBoolean( idTglO, true );

executeAction( idShw, desc2, DialogModes.NO );

};

JJMack
Community Expert
Community Expert
February 11, 2018

Question I see that your script does not replace the current Smart object layer content instead it update the layers  object  opens and edits the object.  It places in the png  and scaled it to fit the object canvas and hides the other content in the object. 

// open smart object;

var smartObject = openSmartObject (theLayer);

var theLayer2 = smartObject.activeLayer;

// place file and fit to convas;

var theNewOne = placeScaleRotateFile (theFiles, 0, 0, 100, 100, 0);

scaleLayerToFitCanvas ();

hideOthers ();

// close;

smartObject.close(SaveOptions.SAVECHANGES);

I think there may be some problems there.  I have never tried to update a smart object layer because of what I though might happen.  If the png image has a transparent borders I think place may trim these.  Additionally the png's file aspect ratio may be different than the work document canvas's aspect ratio so when the place layer is fitted for the canvas size there may be a border because of the aspect ratio mismatch.  Then there is this if the  template's current smart object was a Placed file it may be a raw file or ai file the object may open in ACR or Illustrator not Photoshop.  Are my concerns ill founded?

JJMack
c.pfaffenbichler
Community Expert
Community Expert
February 12, 2018
Additionally the png's file aspect ratio may be different than the work document canvas's aspect ratio so when the place layer is fitted for the canvas size there may be a border because of the aspect ratio mismatch.

The current SO is square, so Replace Contents to some file with another aspect Ratio might cause more issues with the Warp for example.

The Script places the png in the SO and scales to fit according to its longest side.

This seems to make the most sense to me considering that I don’t know if all designs will have the same aspect ratio.

JJMack
Community Expert
Community Expert
February 10, 2018

My script would save Populated template as PSD you can adjust populated images and save out a PNG.  You need to take care when you want to place is png image the transparent borders around an item.   Place and Paste will most likely trim transparent borders to the subject item bounds.  To prevent that when I create the PNG file a put a 1% opaque pixel in the top left and bottom right corners of the documents canvas.  You will never see these pixels amt the will be not transparent borders the Photoshop will trim. If you do not have me scripts search for Photo Collage toolkit https://forums.adobe.com/search.jspa?q=Photo+Collage+toolkit

My scripts will not filter for PNG they will place in any type of image file from a source image folder.  It would be easy to change the extension list to be png only.

To place in images in a particular groups in  order requires you to rename the files with a sort order prefix  which will not be included if you use file nams stamping on placed images.

My Batch Scripts will save PSD files and optionally also save a additional JPG version.  The one image batch script will name save  files with a name that reflects the template and image name.   The Batch multi image script  save files with the a name that reflect the template name a suffix number.  The number is update 1 after a populated template is saved its a count of populated templates.    Many of my scripts do not save a file instead the populated template copy will remain open in Photoshop layered to allow you the tweak the populated template and save out the files you want with the names you want.

JJMack