1

My goal is to be able to batch create a highly scaleable number of "product impression/example" images.

What I have is a Photoshop document, which will serve as a template, with 3 layers (ordered from foreground to background):

Layer 3: a layer with some shadow effects
Layer 2: a perspective transformed smart object containing an image
Layer 1: a stock photo

Layer 1 contains a stock photo with a large picture frame, in which I want to place the image from layer 2. To create a convincing effect, I need to transform and perspective warp the image from layer 2. On top sits layer 3, that casts some shadow to create a convincing effect.

My question is, how can I automate this process? What I want to achieve is that I can select a folder of product images which will then replace the image from layer 2 and export each individual image to a separate folder.

For my case, I can't use a Photoshop variable because that doesn't work with a smart object it seems. The number of images I need to process is in the thousands so doing it manually isn't really an option, plus that I intend to use the same technique on other templates as well.

I'm not restricted to using Photoshop for this task. Inkscape, GIMP, using a trick with Python or Blender or anything else would be perfectly fine as well.

Any help would be greatly appreciated!

7
  • I'm sure this is possible and that someone else will post an answer eventually. But I'm just wondering ... are all these thousands of images for display on a web page? If so, why not do the transformation and shadowing with css on the site? That way the design can be changed later without you having to create yet another version of the images. The change in code will of course cost some time, but maybe less than changing and administrating all those images?
    – Wolff
    Commented Apr 18, 2020 at 14:16
  • @Wolff or imagemagic then the server can do this for you.
    – joojaa
    Commented Apr 18, 2020 at 14:30
  • Also totally possible to do with a JS script but if you need it from scratch (and not to make some modifications to some script that you wrote but you're stuck with something) I'd say it's a paid job... Commented Apr 18, 2020 at 14:45
  • @Wolff Sadly, I need the images as "true" images, so I can submit them into a CMS type system. I wonder if CSS alone might also become cumbersome in the end, if you'd want to make a complex composition (i.e. shadows, multiple layers, transparancy etc). But I really love the out of the box suggestion :)! Commented Apr 19, 2020 at 16:01
  • @SergeyKritskiy Do you mean a JS script for Photoshop? I'm looking into that now, but haven't gotten far enough yet to post anything. Any relevant examples would be more than welcome, though! Once I find a solution, I'll make sure to post it here for future reference and others to see/use Commented Apr 19, 2020 at 16:05

2 Answers 2

2

So I figured out how to answer my own question using Photoshop scripting using Javascript. I thought it would be a good idea to share my solution for others to use it, if they would like, or improve it if they have suggestions!

Result

N distinct versions of the same template image with a nice perspective warp on the content image, each exported with a distinct name. enter image description here

Prerequisites

The only thing you really need is a Photoshop document with at least a smart object/layer named "content". The smart layer itself should contain only one layer; the image you wish to replace. (The script is hardcoded to look for the layer named "content", so you're free to change this name to something else if you wish, just remember to both change the name in you document as well as in the script!)

I have also created two folders. One with input images stored as .jpg, and another one to store output images from the script once they are processed. In my example case, the input folder contains images of some cats.

Description of the script

The steps in my script are the following:

  1. Select the input and output folders
  2. Create an array of filenames out of all the jpg files in the input directory
  3. In the main template PSD file, find (by layer name) the smart layer called 'content'
  4. Open the 'content' layer/smartobject
  5. Open the first replacement file from the array of filenames to be inserted into the smart object
  6. Duplicate the contents from the replacement file into the smart object
  7. Close the replacement file. Save the smart object. Close the smart object.
  8. Export the main template with the image replaced to a jpg in the output folder with the name "{templateName}_{replacementFileName}.jpg"
  9. Move on to the next file in the loop

You could probably optimize this a bit more, but processing a single image only takes about 2 seconds or so, so I'm already quite pleased.

Script

var extension = '.jpg'

// Function that saves a JPEG of the current active document with the name '{name}.jpg'
function saveJpeg(path, templateName, fileName){
    var file = new File(path + '/'  + templateName + '_' + fileName + '.jpg')

    var opts = new JPEGSaveOptions();
    opts.quality = 10;

    templateDocument.saveAs(file, opts, true)
}

var templateDocument = app.activeDocument
var templateName = templateDocument.name.replace('.psd', '')

// From a selected folder, store the filenames of all JPG images in an array so we can loop over them later on
var inFolder = Folder(app.activeDocument.path).selectDlg("Please select folder of images to process");
if (inFolder != null)
{
  var fileList = inFolder.getFiles('*' + extension);
}

// Select a folder to store all the output images
var outFolder = Folder(app.activeDocument.path).selectDlg("Please select folder to export processed images");

// Loop over all the images that need to be processed, and store each result in '{outFolder}/{templateName}_{fileList[i]}.jpg'
for(var i = 0; i < fileList.length; i++){
    // Inside the template document, look for the smart layer called 'content'. Open the smart layer so it can be edited
    var contentLayer = templateDocument.layers.getByName('content')
    app.activeDocument.activeLayer = contentLayer;
    executeAction(stringIDToTypeID("placedLayerEditContents"));

    // Create a variable to store the environment of the smart layer
    var smartObject = app.activeDocument

    // Open the file fileList[i] in a new windows, duplicate it to the smart layer
    var openedFile = open(fileList[i]);
    var imageSource = app.activeDocument
    imageSource.artLayers[0].duplicate(smartObject);

    // Get the name from the image so we can use it in our export filename, and close fileList[i] again (without saving etc)
    var imageSourceName = imageSource.name.replace(extension, '')
    imageSource.close();

    // Remove the previously applied image at the bottom of the stack of layers inside the smart layer, to prevent it from accumulating more and more images
    smartObject.artLayers[1].remove()

    // Save and close the smart layer
    smartObject.save();
    smartObject.close();

    // Export a jpg from the original template document with our newly replaced layer
    saveJpeg(outFolder, templateName, imageSourceName)
}

And that's about it! If you like the script feel free to upvote, and if you have suggestions for improvements they would be more than welcome!

1

Thanks for your script. I just added a resizing of the image source and a line to close it without saving changes so that th script is not interrupted by a prompt.

imageSource.close(SaveOptions.DONOTSAVECHANGES);

// these are our values for the END RESULT width and height (in pixels) of our image
    var fWidth = 1160;
    var fHeight = 1160;

    // do the resizing.  if height > width (portrait-mode) resize based on height.  otherwise, resize based on width
    if (imageSource.height > imageSource.width) {
        imageSource.resizeImage(null,UnitValue(fHeight,"px"),null,ResampleMethod.BICUBIC);
    }
    else {
        imageSource.resizeImage(UnitValue(fWidth,"px"),null,null,ResampleMethod.BICUBIC);
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.