Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
1

How to accelerate speed / reduce runtime of gigantic Photoshop batches/scripts?

Participant ,
Jul 04, 2023 Jul 04, 2023

Part of my automated workflow involves running 13 total steps on a large number of images (1000+). While this entire workflow is fully automated, the runtime is gigantic (5-10 hours, for the recent batch sizes), given how many image files it's processing.

 

What are some of my options for effectively reducing the runtime of this Photoshop script?

 

The obvious options include: eliminate steps; get a faster computer with better hardware; reduce the Photoshop file sizes so it can process faster; and dedicate more CPU resources during runtime to the program so it can execute faster.

 

Are there any other solutions I'm missing that help to speed up batches and scripts? Maybe writing the code differently so it more efficiently performs the actions?

 

Just looking for some good ideas for how I can reduce the runtime.

 

Thanks!

TOPICS
Actions and scripting , Windows
2.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Jul 04, 2023 Jul 04, 2023

Is this an action or script?

 

What are the 13 steps?

 

Identify the bottlenecks at each of the 13 steps. Perhaps batch editing in ACR or LightRoom for specific steps may speed up the entire process, even if this means breaking up one large batch process into smaller steps. Look into other software which performs batch tasks more efficiently for one or more steps.

 

https://community.adobe.com/t5/photoshop-ecosystem-discussions/batch-action-crashes-after-7-077-file...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 04, 2023 Jul 04, 2023

There's a few more included but here are some of the key functions from the .jsx file:

// Function to check if a document is already flattened
function isDocumentFlattened(doc) {
    var layers = doc.layers;
    for (var i = 0; i < layers.length; i++) {
      if (layers[i].typename !== "Layer") {
        return false;
      }
    }
    return true;
  }
 
  // Get the folder containing the images
  var folderPath = "C:\\Users\\anton\\Pictures\\current image folder";
 
  // Open each image in the folder
  var folder = new Folder(folderPath);
  var fileList = folder.getFiles(/\.(jpg|jpeg|png|gif|bmp)$/i);
 
  for (var i = 0; i < fileList.length; i++) {
    var file = fileList[i];
 
    if (file instanceof File) {
      // Open the document
      var doc = app.open(file);
 
      // Check if the document is already flattened
      if (!isDocumentFlattened(doc)) {
        // Flatten the document
        doc.flatten();
 
        // Save changes and close the document
        doc.save();
        doc.close(SaveOptions.DONOTSAVECHANGES);
      } else {
        // Close the document without saving changes
        doc.close(SaveOptions.DONOTSAVECHANGES);
      }
    }
  }
 
function runBatchAction(inputPath, outputPath, actionName, actionSet, wildcard) {
    wildcard = wildcard || /\.(jpg|png)$/i;
    var files = new Folder(inputPath).getFiles(function(file) { return wildcard.test(file.name) });

    var options = new BatchOptions();
    options.destination = BatchDestinationType.FOLDER;
    options.destinationFolder = new Folder(outputPath);
    options.overrideOpen = false;
    options.overrideSave = true;

    options.fileNaming = [FileNamingType.DOCUMENTNAMEMIXED, FileNamingType.EXTENSIONLOWER];
    app.batch(files, actionName, actionSet, options);
 
    // After batch processing, iterate over the files and replace dashes with spaces
    var outputFolder = new Folder(outputPath);
    var outputFiles = outputFolder.getFiles();
    for (var i = 0; i < outputFiles.length; i++) {
        var outputFile = outputFiles[i];
        if (outputFile.name.indexOf('-') !== -1) {
            var newFileName = outputFile.name.replace(/-/g, ' ');
            outputFile.rename(newFileName);
        }
    }
}
 
function SmartObjectReplacementProduct(PhotoshopFilepathToUse) {
    var filePath = PhotoshopFilepathToUse;
    var fileRef = new File(filePath);
    var docRef = app.open(fileRef);
    BatchReplaceSmartObject(CanvasProductImages);
    docRef.close(SaveOptions.DONOTSAVECHANGES);
}

function SmartObjectReplacementRoom(PhotoshopFilepathToUse) {
    var filePath = PhotoshopFilepathToUse;
    var fileRef = new File(filePath);
    var docRef = app.open(fileRef);
    BatchReplaceSmartObject(CanvasRoomImages);
    docRef.close(SaveOptions.DONOTSAVECHANGES);
}

function BatchReplaceSmartObject(ImageFolderToUse) {
    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
        var 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
          var theFiles = new Folder(ImageFolderToUse).getFiles(getFiles);
          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
              myDocument.saveAs((new File(thePath + "/" + theName + "_" + theNewName + ".jpg")), jpgSaveOptions, true, Extension.LOWERCASE);
              // Close the processed document to release memory
              theFiles[m].close(SaveOptions.DONOTSAVECHANGES); // this line apparently doesn't actually do anything

              // Purge all caches to free up memory
              app.purge(PurgeTarget.ALLCACHES); // not sure all 4 are needed, just doing it to be thorough
              app.purge(PurgeTarget.CLIPBOARDCACHE);
              app.purge(PurgeTarget.HISTORYCACHES);
              app.purge(PurgeTarget.UNDOCACHES);
            }
           

          }
        }
      }
     
      // 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;
      }
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 04, 2023 Jul 04, 2023

I did just realize in looking at this that I could combine two steps to decrease the runtime. The previous step opens each image file and performs a specified Photoshop edit on it. At that step I could just make the final step flatten the image. Then I won't have to run a whole separate batch where I open all images again to flatten then save them again. I'll just add one more step while already opening/saving them the first time around.

 

I also do another set of batches at the very end, where AFTER doing the smart-object replacement? I again open all images, then save them as a smaller compressed version. I see zero reason why I couldn't just include that specified save operation INSIDE of the code that batch-replaces the smart objects then saves each image as a JPEG. Since opening/saving files seems to be a pretty "expensive" operation in terms of runtime? This SHOULD help to streamline the code.

 

Implemented these changes, tested the scripts and here are the results:

ORIGINAL VERSION: 360 seconds
OPTIMIZED VERSION: 197 seconds
ORIGINAL VERSION = 1.8x MORE RUNTIME for identical end-results

In other words, this optimized version is almost 2x faster.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 04, 2023 Jul 04, 2023

I'm wondering if there are some big-picture computer solutions. Maybe we can do something like, put Photoshop into some kind of like "maximum focus" mode where everything is minimized and ALL it does is execute the script with maximum efficiency? Or something similar in Windows 10 where I can say: "Until this script is fully done executing? Put EVERYTHING else on hold and dedicate the MAXIMUM amount of resources to getting this done?"

Like I don't need some Microsoft Edge update to run in the background, etc. I just need my computer's full set of resources entirely dedicated to running this one program with maximum efficiency. Any way I can set it up so my computer dedicates itself in that way?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 05, 2023 Jul 05, 2023

I might suggest that before running these kind of intensive scripts that the number of History steps be reduced to a bare minimum, like 2. This should reduce the time it takes for Photoshop to write History undos which will be written to the scratch drive if actual memory is saturated.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 05, 2023 Jul 05, 2023

Yes, reducing History States before launching is a good call and actually something I was forced to implement at an earlier stage because this set of scripts would keep crashing Photoshop without it. I also programmatically wipe the History States periodically inside of the script as it runs. Not sure it technically helps much to do that, but I've noticed that with these two steps in place, it allows me to run enormous batches without causing the computer/Photoshop to slow down and run hot.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 05, 2023 Jul 05, 2023

• Use AM-code instead of DOM-code if possible (for example to replace the for-clause »for (var i = 0; i < layers.length; i++) {«)

• Hide the Panels 

• Zoom out (not sure how much this helps) 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 05, 2023 Jul 05, 2023

"• Use AM-code instead of DOM-code if possible (for example to replace the for-clause »for (var i = 0i < layers.lengthi++) {«)"

Interesting. Does AM code tend to run faster than DOM code?

"• Hide the Panels"

I've heard this one but never thought to try it. I might try to put Photoshop into some kind of "absolutely everything minimized//hidden/and it's full screen on the current tab only" mode to see if that actually does improve the speed. I'm not sure that it would, but if it takes time for the additional panels to load and render each time it opens and closes a document, I could imagine how it would give it a slight performance boost. I might integrate this, compare the execution times of a test, and see how it goes.

"Zoom out"

Honestly I don't see any good reason why this would help. Maybe by keeping it really zoomed out, it technically loads a smaller number of pixels to display, and is able to therefore run faster? I'm a little more skeptical of this one, but again, it's worth testing to compare the results.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2023 Jul 06, 2023
LATEST
quote

Interesting. Does AM code tend to run faster than DOM code?

Usually AM code runs faster than DOM code. 

But there might be cases where it does not. 

 

quote

I might try to put Photoshop into some kind of "absolutely everything minimized//hidden/and it's full screen on the current tab only" mode to see if that actually does improve the speed. 

I wonder if hiding Panels like Layers, Channels, Paths, Histogram, Properties, History, Info, Layer Comps that display document-specific information/previews would suffice to get the speed-increase. 

Toolbar, Brushes, Styles, Actions etc. don’t need to change with a changing document so theoretically they might be irrelevant in this regard. 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 05, 2023 Jul 05, 2023

So I implemented a simple app.togglePalettes() command at the start of the script (then I revert it back at the very end), and I found that the script runtime WAS decreased by a decent amount:

 

ORIGINAL VERSION: 360 seconds
OPTIMIZED VERSION 1: 197 seconds
ORIGINAL VERSION = 1.8x MORE RUNTIME for identical end-results
OPTIMIZED VERSION 2 (app.togglePalettes() implemented): 174 seconds
ORIGINAL VERSION = 2.07x MORE RUNTIME for identical end-results

While I haven't tested it yet, zooming out is something that needs to be done specific to a given document. Since it'll load at the default setting, THEN you'll need to command it to zoom out, I really just can't imagine that there's any serious performance boost this will give the script.

I did have another idea that's slightly crazy: I'm wondering if there's some way for me to tell Photoshop, while the script runs: "Don't even display anything visually on the screen to me. Just run the commands/operations on the files and dedicate full resources to THAT -- don't worry about rendering anything visually to me." Not sure that's possible or an option, however since this is fully automated, there's really no need for Photoshop/my computer to waste any resources to rendering this stuff as it runs.

 

I supposed I COULD try to just, minimize Photoshop as it runs the script. So then it would functionally be doing that. However I don't know if scripts will even work with Photoshop fully minimized like that. I have actions that are contingent on getting the current active layer, things like that, and my concern is trying to run this script with it minimized will just cause it to fail.

 

I did have one final idea: There are two steps in the workflow that MIGHT be able to be eliminated. The workflow takes the starting image, resizes it so it will fit optimally inside of a later Smart Object, then later we batch-replace the smart objects and save as JPEGs. It resizes the images in two different ways, depending on the needs of each Smart Object. I MIGHT be able to just, change the sizes of the Smart Objects in the documents themselves, so the default images are already optimally sized to be replaced inside of the Smart Object in their original starting form. This would completely eliminate the need for those two steps and would probably allow me to AGAIN cut the runtime down in half.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Jul 05, 2023 Jul 05, 2023

Theoretically (I did not check) you can split the folder into 10 parts, run 10 photoshops at the same time and start your own process in each to process the desired subfolder.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 06, 2023 Jul 06, 2023

Without having tested it, I feel quite confident that running 10 parallel instances of Photoshop would absolutely slow my computer to a crawl. Maybe if I had 200 GB RAM, lol.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines