Skip to main content
Andrew Bold
Known Participant
January 25, 2023
Answered

Slow operation of the script

  • January 25, 2023
  • 4 replies
  • 922 views

Hi. Once found a script and modified it to suit my needs. It works fine, but it's slow.
I use it for batch processing.
When I manually save for web, I don't notice such delays. Maybe the script itself is a bit crooked?

The goal is to save a file with an existing color profile, jpg, up to 500kb, in the same folder, with the same name.
The file height and width are already correct before saving, the script should only save with the requirements above.

(Analogous to the "save for web" function, which the action doesn't see)

var docRef = activeDocument;
var outputFolder = docRef.path;

var currentNameWithoutExtension = docRef.name.split(".")[0];
NamesaveRef = new File( outputFolder + "/" + currentNameWithoutExtension + ".jpg" );
var NewfileRef = new File( NamesaveRef )

// quality/size constraints
var MaxSz =  500000; // max. 500Kb
var Qlt = 100; // initial quality 100
var x = 1; // decreasing step

// Perform the first SaveForWeb Operation
ExpWeb(NewfileRef, Qlt);

// Keep trying to save the file with max. Qlt, but under MaxSz    
while (NewfileRef.length > MaxSz)
{
      Qlt = Qlt - x;
      NewfileRef = new File( NewfileRef );  
      NewfileRef.remove();
      ExpWeb(NewfileRef, Qlt);  // Perform a new SaveForWeb Operation, with slightly lower Qlt
         if (Qlt <= 10) {
           alert("The file can't be saved with the desired size AND quality.");
           break  // break the loop whenever the quality is as low as 50 (this shouldn't need to happen)
         }
}

var FileSz = NewfileRef.length/1024;
FileSz = Math.round(FileSz);

// SaveForWeb Export, with the desired constraints and parameters
function ExpWeb(FileNm, Qlt)
{
      var options = new ExportOptionsSaveForWeb();
      options.includeProfile = true;
      options.quality = Qlt;   // Start with highest quality (biggest file).
      options.format = SaveDocumentType.JPEG;   // Save Format for the file
      docRef.exportDocument(File(FileNm), ExportType.SAVEFORWEB, options);
}
Correct answer Stephen Marsh

It would appear to be reasonable to expect that the script is slow, it has to save, then check the file size on disk, and if the file size isn't to the target, delete the file and repeat again with a 1% lesser value, until it is below the target size on disk.

 

Starting at quality 100 most likely isn't helping. Find the quality value that produces a reasonable looking result. This could be 90 or some other start point value below 100. I understand that 100 is "ideal", however, when you compare a lesser value you may find that the visual quality is comparable, however, this may save multiple iterations of the script needlessly running until it produces the desired outcome. Another option would be to increase the decreasing quality step from 1 to 5.

4 replies

Stephen Marsh
Community Expert
Community Expert
July 24, 2026

An update while working on a related script for batching.

 

 

Edit the script code to set HEADLESS_MODE to true to run without showing the target-size dialog, which is useful for recording into an action for batch/automation. When set to true, the script uses MaxSz hard-coded value as the target size in bytes and skips the dialog.

 

When HEADLESS_MODE is set to false, the dialog is shown so the user can confirm/override the hard-coded target size interactively via the script GUI.

 

/*
JPEG Save for Web to Target KB File Size
Original Script:
https://community.adobe.com/questions-712/slow-operation-of-the-script-1149419
Updated by Stephen Marsh
v1.0 - 3rd July 2026: GUI Added
Related scripts:
https://codebybrett.github.io/savesmalljpeg/
https://mindfulretouch.com/the-course/saving/saving-quality/
*/

////////////////////
// Set HEADLESS_MODE to true to run without showing the target-size dialog, which is
// useful for batch/automation. When set to true, the script uses MaxSz (as set below)
// as the target size in bytes and skips the dialog.
//
// When HEADLESS_MODE is set to false, the dialog is shown so the user can confirm/override
// the target size interactively.
////////////////////
// User script execution Preference
var HEADLESS_MODE = false;
////////////////////
// Set the target size, i.e. 500000 = max. bytes (500Kb)
var MaxSz = 500000; // Also used as the headless target size, change as needed!
////////////////////

// Check that a document is open before proceeding
if (app.documents.length === 0) {
alert("No document is open! Please open a document and try again.");
throw new Error("__CANCEL__");
}

var docRef = activeDocument;
var outputFolder = docRef.path;
var currentNameWithoutExtension = docRef.name.replace(/\.[^\.]+$/, '');

NamesaveRef = new File(outputFolder + "/" + currentNameWithoutExtension + ".jpg");
var NewfileRef = new File(NamesaveRef);
var FileSz = NewfileRef.length / 1024;
FileSz = Math.round(FileSz);

////////////////////
var Qlt = 90; // Initial JPEG save quality value
var x = 5; // Decreasing quality step % value
////////////////////

var iterations = 0; // Tracks the number of Save for Web export passes

if (HEADLESS_MODE) {
// Headless: skip the dialog entirely, use MaxSz as-is (already in bytes).
} else {
// Show the dialog to let the user set/confirm the target size (in KB)
var dialogResult = showTargetSizeDialog(MaxSz);

if (dialogResult === null) {
// User cancelled
throw new Error("__CANCEL__");
}

MaxSz = dialogResult; // MaxSz is stored in bytes
}

// Perform the first SaveForWeb JPEG Operation
s4wJPEG(NewfileRef, Qlt);
iterations++;

// Keep trying to save the file with max. Qlt, but under MaxSz
while (NewfileRef.length > MaxSz) {
Qlt = Qlt - x;
NewfileRef = new File(NewfileRef);
NewfileRef.remove();
s4wJPEG(NewfileRef, Qlt); // Perform a new SaveForWeb Operation, with slightly lower Qlt
iterations++;
if (Qlt <= 50) {
alert("The file can't be saved with the desired size AND quality.");
break; // break the loop whenever the quality is as low as 50 (this shouldn't need to happen)
}
}

// End of script notification
if (!HEADLESS_MODE) {
app.beep();
alert("Save Iterations: " + iterations + " \r " +
"File Size: " + Math.round(NewfileRef.length / 1024) + " KB"); // Matches Windows Explorer
}


///// Functions /////

function s4wJPEG(FileNm, Qlt) {
var options = new ExportOptionsSaveForWeb();
options.includeProfile = true;
options.quality = Qlt; // Start with highest quality (biggest file).
options.format = SaveDocumentType.JPEG; // Save Format for the file
docRef.exportDocument(File(FileNm), ExportType.SAVEFORWEB, options);
}

function showTargetSizeDialog(defaultSzBytes) {
var defaultSzKB = Math.round(defaultSzBytes / 1000); // Not 1024!?

// ScriptUI
var win = new Window("dialog", "JPEG Save for Web Target Size (KB) - v1.0");
win.orientation = "column";
win.alignChildren = ["fill", "top"];
win.spacing = 10;
win.margins = 16;

// Panel containing the target size entry field
var panel = win.add("panel", undefined, "");
panel.orientation = "row";
panel.alignChildren = ["left", "center"];
panel.margins = [15, 20, 15, 15];
panel.spacing = 10;

panel.add("statictext", undefined, "Max size (KB):");
var szInput = panel.add("editnumber", undefined, String(defaultSzKB));
szInput.characters = 10;

// Button row, right aligned, outside/below the panel
var btnGroup = win.add("group");
btnGroup.orientation = "row";
btnGroup.alignment = ["right", "top"];
btnGroup.spacing = 10;

var cancelBtn = btnGroup.add("button", undefined, "Cancel", {
name: "cancel"
});
var okBtn = btnGroup.add("button", undefined, "OK", {
name: "ok"
});

var result = null;

okBtn.onClick = function() {
var val = parseFloat(szInput.text);
if (isNaN(val) || val <= 0) {
alert("Please enter a valid target size in KB (a positive number).");
return;
}
result = Math.round(val * 1024); // convert KB back to bytes
win.close();
};

cancelBtn.onClick = function() {
result = null;
win.close();
};

win.show();

return result;
}

 

Participating Frequently
July 11, 2023

Hi i copied the above code into notepad and then saved as a .jsx then loaded it into a photoshop action but nothing seems to be happening when i play the action? i am i missing a step? 

 

Regards

 

Simon

Andrew Bold
Known Participant
July 11, 2023

Hi. Try setting the .js format. And try again

Legend
January 26, 2023

Have you looked at Image Processor Pro to see if it would do what you need?

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
January 25, 2023

It would appear to be reasonable to expect that the script is slow, it has to save, then check the file size on disk, and if the file size isn't to the target, delete the file and repeat again with a 1% lesser value, until it is below the target size on disk.

 

Starting at quality 100 most likely isn't helping. Find the quality value that produces a reasonable looking result. This could be 90 or some other start point value below 100. I understand that 100 is "ideal", however, when you compare a lesser value you may find that the visual quality is comparable, however, this may save multiple iterations of the script needlessly running until it produces the desired outcome. Another option would be to increase the decreasing quality step from 1 to 5.

Andrew Bold
Known Participant
January 28, 2023

Indeed) I reduced the initial quality and increased the number of steps, then the script became super fast, without visual changes to the picture.

Thanks for the tip)

Stephen Marsh
Community Expert
Community Expert
January 28, 2023

You're welcome, thanks for coming back to update the topic with a reply and correct answer.

 

Edit: While on this topic...

 

/*
https://mindfulretouch.com/the-course/saving/saving-quality/
*/

var doc = app.activeDocument;
var filename = doc.name;
var foldername = doc.path.name;
var filepath = doc.path;
var parentfilepath = doc.path.parent
var jpegQuality = 70; // desired quality
var maxfilesize = 512000; // max size in bytes
var dec = 5; // decreasing step
var minimumqual = 50; //minumum desired quality
savefolder = new Folder(filepath + '/BATCH/');
savefolder.create();
saveFile = new File(savefolder + '/' + filename.split('.').slice(0, -1).join('.') + ".jpg");
doc.flatten();
doc.pathItems.removeAll();
doc.channels.removeAll();

function savebatchweb(saveFile, jpegQuality) {
    var sfwOptions = new ExportOptionsSaveForWeb();
    sfwOptions.format = SaveDocumentType.JPEG;
    sfwOptions.includeProfile = true;
    sfwOptions.interlaced = 0;
    sfwOptions.optimized = true;
    sfwOptions.quality = jpegQuality;
    doc.exportDocument(saveFile, ExportType.SAVEFORWEB, sfwOptions);
}
savebatchweb(saveFile, jpegQuality);
while (saveFile.length > maxfilesize) {
    jpegQuality = jpegQuality – dec;
    saveFile = new File(saveFile);
    saveFile.remove();
    savebatchweb(saveFile, jpegQuality);
    if (jpegQuality <= minimumqual) {
        break
    }
}
doc.close(SaveOptions.DONOTSAVECHANGES); //closes file