Skip to main content
eznewmedia
Participating Frequently
December 7, 2023
Answered

Looking for Action or Script to Resize and Save WebP Files

  • December 7, 2023
  • 7 replies
  • 6566 views

For a new website build, we were originally asked to save Webp images at 2048 pixels in width.  Now, they want those images to be 1000 pixels wide.  There are THOUSANDS of images in dozens of folders that need to be resized, so I thought I would create a simple action to run in a batch process to resize all the images in the master folder and sub folders, and then save to another folder.  Easy enough; however, when Photoshop goes to save the new WebP image during the batch process in the new folder, it stops and waits for me to choose the compression level of the new WebP image, which I would need to manually do for each image, which won't work. I've seen a script to resize images, and another that converts images to WebP and automatically save them, but nothing that combines both functions.  Can anyone help? 

 

Here is the script to open images in one folder, and then save WebP images in another folder:

 

https://community.adobe.com/t5/photoshop-ecosystem-discussions/batch-process-images-to-webp/m-p/14109084

 

Is it possible to add a command in the middle of that script to resize the images to 1000 pixels in width?

 

Thanks for the help!

This topic has been closed for replies.
Correct answer Stephen Marsh

That must be it Stephen ... and the latest version of Photoshop produced the same dialogue (image attached).  In your first script,  you had compression parameters:

// Compression parameters = "compressionLossless" | "compressionLossy"
                descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                var WebPCompIsLossless = false; // set the default flag for compression
                if (WebPCompIsLossless == false) {
                    // 0 (lowest lossy quality) - 100 (highest lossy quality)
                    descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                }

 

I don't see those in the second script, and the Photoshop dialogue is asking for a compression setting before saving in the pop up.  If you add that language to your second script, would that fix the issue??


The second script just saves, it assumes that the WebP values are known from the file metadata, which worked for my test files...but who knows how your WebP files were saved.

 

Yes, the entire save as WebP function would need to be used.

 

 l'll look into it later...

 

EDIT:

 

@eznewmedia 

 

Try this 1.2 version:

 

/*
Batch Save As WebP 1000px Wide.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.2 - 8th December 2023, Stephen Marsh
Special thanks to Paul MR for the recursive folder processing code:
photoshopgurus.com/forum/threads/batch-and-subfolders.22134/
*/

#target photoshop

    (function () {

        if (app.documents.length === 0) {

            // Ensure that version 2022 or later is being used
            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);

            // Fail
            if (versionCheck < 23) {
                alert("You must use Photoshop 2022 or later to save using native WebP format...");
                return;

                // Pass
            } else {

                if (confirm('This script will resave all WebP files to 1000px wide. All sub-folders under the selected input folder will be processed. Continue?', false)) {

                    var imageFolder = Folder.selectDialog('Select the top-level folder:');

                    var origDialogs = app.displayDialogs;
                    app.displayDialogs = DialogModes.NO;

                    // Script Execution Timer - Function    
                    var timeDiff = {
                        setStartTime: function () {
                            d = new Date();
                            time = d.getTime();
                        },
                        getDiff: function () {
                            d = new Date();
                            t = d.getTime() - time;
                            time = d.getTime();
                            return t;
                        }
                    };

                    // Script Execution Timer - Start    
                    timeDiff.setStartTime();

                    // Set the file processing counter
                    var fileCounter = 0;

                    if (imageFolder != null) processFolder(imageFolder);

                    function processFolder(folder) {
                        var fileList = folder.getFiles()
                        for (var i = 0; i < fileList.length; i++) {
                            var file = fileList[i];
                            if (file instanceof File && file.name.match(/\.webp/i)) {
                                open(file);
                                // Start Main Code Block
                                activeDocument.resizeImage(UnitValue(1000, "px"), null, null, ResampleMethod.BICUBIC); // width, height, resolution, method
                                saveWebP("compressionLossy", 75, true, true, true, true);
                                activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                                fileCounter++;
                                // End Main Code Block
                                function saveWebP(compType, compValue, xmpData, exifData, psData, asCopy) {
                                    /*
                                    v1.1 - 12th March 2023, Stephen Marsh
                                    https://community.adobe.com/t5/photoshop-ecosystem-discussions/saving-webp-image-by-script/td-p/13642577
                                    */
                                    // Doc and path save variables
                                    var WebPDocName = activeDocument.name.replace(/\.[^\.]+$/, ''); // Remove file extension
                                    var WebPSavePath = activeDocument.path.fsName + "/" + WebPDocName + ".webp" // Change path as needed
                                    var WebPFile = new File(WebPSavePath); // Create the file object

                                    /*
                                    // Check for existing file object
                                    if (WebPFile.exists) {
                                        // true = 'No' as default active button
                                        if (!confirm("File exists, overwrite: Yes or No?", true))
                                            // throw alert("Script cancelled!");
                                            throw null;
                                    }
                                    */

                                    function s2t(s) {
                                        return app.stringIDToTypeID(s);
                                    }
                                    var descriptor = new ActionDescriptor();
                                    var descriptor2 = new ActionDescriptor();

                                    // Compression parameters = "compressionLossless" | "compressionLossy"
                                    descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                                    var WebPCompIsLossless = false; // set the default flag for compression
                                    if (WebPCompIsLossless == false) {
                                        // 0 (lowest lossy quality) - 100 (highest lossy quality)
                                        descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                                    }

                                    // Metadata options
                                    descriptor2.putBoolean(s2t("includeXMPData"), xmpData); // Boolean param moved to function call
                                    descriptor2.putBoolean(s2t("includeEXIFData"), exifData); // Boolean param moved to function call
                                    descriptor2.putBoolean(s2t("includePsExtras"), psData); // Boolean param moved to function call

                                    // WebP format and save path
                                    descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
                                    descriptor.putPath(s2t("in"), WebPFile); // Save path variable

                                    // Save As = false | Save As a Copy = true
                                    descriptor.putBoolean(s2t("copy"), asCopy); // Boolean param moved to function call

                                    // The extension
                                    descriptor.putBoolean(s2t("lowerCase"), true);

                                    // Execute the save
                                    executeAction(s2t("save"), descriptor, DialogModes.NO); // Change NO to ALL for dialog
                                }
                            } else
                            if (file instanceof Folder) {
                                processFolder(file);
                            }
                        }
                    }

                    // End of script
                    app.displayDialogs = origDialogs;
                    alert('Batch resize and WebP overwrite completed!' + '\r' + fileCounter + ' WebP files processed' + '\r' + '(' + timeDiff.getDiff() / 1000 + ' seconds)');
                }
            }

        } else {
            alert('Please close all open documents before running this script!');
        }
    }());

 

 

 

7 replies

Stephen Marsh
Community Expert
Community Expert
April 11, 2024

@JonDemand 

 

This 1.2 version adds a log text file to the output folder, listing any skipped files that would have overwritten an existing file.

 

Batch Save As WebP and Fit Longest Edge to 1000px Wide v1-2.jsx
 
/*
Batch Save As WebP and Fit Longest Edge to 1000px Wide v1-2.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.2 - 11th April 2024, Stephen Marsh
NOTE:
The output folder should NOT be under the same path as the input folder!
*/

#target photoshop

    (function () {

        if (app.documents.length === 0) {

            // Ensure that version 2022 or later is being used
            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);

            // Fail
            if (versionCheck < 23) {
                alert("You must use Photoshop 2022 or later to save using native WebP format...");
                return;

                // Pass
            } else {

                // Optionally run a specified action
                //var actionName = "Molten Lead"; // Action to run, change as needed
                //var actionSet = "Default Actions"; // Action set to run, change as needed

                if (confirm('This script will proportionally fit all supported files to 1000px on the longest edge. All sub-folders under the selected input folder will be processed. Continue?', false)) {

                    // Root/top-level input folder
                    var imageFolder = Folder.selectDialog('Select the root/top-level folder to process:');
                    // The output folder should NOT be under the same path as the input folder!
                    var outputFolder = Folder.selectDialog("Please select the output folder to save the WebP files to:");
                    // To do: add supporting code to check for this

                    var origDialogs = app.displayDialogs;
                    app.displayDialogs = DialogModes.NO;

                    // Script Execution Timer - Function    
                    var timeDiff = {
                        setStartTime: function () {
                            d = new Date();
                            time = d.getTime();
                        },
                        getDiff: function () {
                            d = new Date();
                            t = d.getTime() - time;
                            time = d.getTime();
                            return t;
                        }
                    };

                    // Script Execution Timer - Start    
                    timeDiff.setStartTime();

                    // Set the input file processing counter
                    var inputFileCounter = 0;
                    // Set the output file processing counter
                    var fileCounter = 0;

                    if (imageFolder != null) processFolder(imageFolder);

                    function processFolder(folder) {
                        // Special thanks to Paul MR for the recursive folder processing code:
                        // photoshopgurus.com/forum/threads/batch-and-subfolders.22134/
                        var fileList = folder.getFiles()
                        for (var i = 0; i < fileList.length; i++) {
                            var file = fileList[i];
                            if (file instanceof File && file.name.match(/\.(webp|tif|tiff|jpg|jpeg|psd|psb|png)$/i)) {

                                open(file);

                                /* Start Main Code Block */

                                // Proportionally fit image to 1000px on the longest edge
                                fitImage(1000, 1000);

                                /////
                                // If the doc isn't in RGB mode
                                if (activeDocument.mode !== DocumentMode.RGB) {

                                    // Convert to sRGB & 8 bpc
                                    activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.changeMode(ChangeMode.RGB);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                                    // If the doc is in RGB mode
                                } else {
                                    // Convert to sRGB & 8 bpc
                                    //activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                                }

                                // Increment the input file saving counter
                                inputFileCounter++

                                /* End Main Code Block */

                            } else
                            if (file instanceof Folder) {
                                processFolder(file);
                            }
                        }
                    }

                    // End of script
                    app.displayDialogs = origDialogs;
                    app.beep();
                    alert('Batch resize and save to WebP completed!' + '\r' + inputFileCounter + ' source files' + '\r' + fileCounter + ' WebP files saved' + '\r' + '(' + timeDiff.getDiff() / 1000 + ' seconds)');
                    // Open the output folder in the Finder or Explorer
                    outputFolder.execute();
                }
            }

        } else {
            alert('Please close all open documents before running this script!');
        }

        ///// FUCTIONS /////

        function fitImage(fWidth, fHeight) {
            /* NEARESTNEIGHBOR | BILINEAR | BICUBIC | BICUBICSMOOTHER | BICUBICSHARPER | BICUBICAUTOMATIC */
            if (activeDocument.height.value > activeDocument.width.value) {
                activeDocument.resizeImage(null, UnitValue(fHeight, "px"), null, ResampleMethod.BICUBIC);
            } else {
                activeDocument.resizeImage(UnitValue(fWidth, "px"), null, null, ResampleMethod.BICUBIC);
            }
        }

        function saveWebP(compType, compValue, xmpData, exifData, psData, asCopy) {
            /*
            v1.1 - 12th March 2023, Stephen Marsh
            https://community.adobe.com/t5/photoshop-ecosystem-discussions/saving-webp-image-by-script/td-p/13642577
            */
            // Doc and path save variables
            var WebPDocName = activeDocument.name.replace(/\.[^\.]+$/, ''); // Remove file extension
            var WebPSavePath = outputFolder + "/" + WebPDocName + ".webp" // Change path as needed
            var WebPFile = new File(WebPSavePath); // Create the file object

            // Check for existing file object
            if (WebPFile.exists) {
                try {
                    var os = $.os.toLowerCase().indexOf("mac") >= 0 ? "mac" : "windows";
                    if (os === "mac") {
                        logFileLF = "Unix"; // Legacy = "Macintosh"
                    } else {
                        logFileLF = "Windows";
                    }
                    var logFile = new File(outputFolder + "/" + "Batch-WebP-to-1000px.log");
                    if (logFile.exists)
                        logFile.remove();
                    logFile.open("a");
                    logFile.encoding = "UTF-8";
                    logFile.lineFeed = logFileLF;
                    logFile.write("The following input file creates a duplicate output file and was skipped:" + "\r" + app.activeDocument.path.fsName + "/" + app.activeDocument.name + "\r");
                    logFile.close();
                } catch (e) {
                    alert(e + ': Line ' + e.line);
                }
            } else {
                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();

                // Compression parameters = "compressionLossless" | "compressionLossy"
                descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                var WebPCompIsLossless = false; // set the default flag for compression
                if (WebPCompIsLossless == false) {
                    // 0 (lowest lossy quality) - 100 (highest lossy quality)
                    descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                }

                // Metadata options
                descriptor2.putBoolean(s2t("includeXMPData"), xmpData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includeEXIFData"), exifData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includePsExtras"), psData); // Boolean param moved to function call

                // WebP format and save path
                descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
                descriptor.putPath(s2t("in"), WebPFile); // Save path variable

                // Save As = false | Save As a Copy = true
                descriptor.putBoolean(s2t("copy"), asCopy); // Boolean param moved to function call

                // The extension
                descriptor.putBoolean(s2t("lowerCase"), true);

                // Execute the save
                executeAction(s2t("save"), descriptor, DialogModes.NO); // Change NO to ALL for dialog

                // Increment the file saving counter
                fileCounter++;
            }
        }
    }());

 

Stephen Marsh
Community Expert
Community Expert
April 11, 2024

@JonDemand 

 

This 1.1 version script will skip over duplicate destination/output files. The input file count and the output file count are reported in the alert at the end of the script, so hopefully you will have some idea that the two quantities don't match. With a little more work, duplicate file paths and names could be silently written to a log file.

 

Note: The selected output folder should be empty for the reported file count to be correct.

 

Batch Save As WebP and Fit Longest Edge to 1000px Wide v1-1.jsx

 

/*
Batch Save As WebP and Fit Longest Edge to 1000px Wide v1-1.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.1 - 11th April 2024, Stephen Marsh
NOTE:
The output folder should NOT be under the same path as the input folder!
*/

#target photoshop

    (function () {

        if (app.documents.length === 0) {

            // Ensure that version 2022 or later is being used
            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);

            // Fail
            if (versionCheck < 23) {
                alert("You must use Photoshop 2022 or later to save using native WebP format...");
                return;

            // Pass
            } else {

                // Optionally run a specified action
                //var actionName = "Molten Lead"; // Action to run, change as needed
                //var actionSet = "Default Actions"; // Action set to run, change as needed

                if (confirm('This script will proportionally fit all supported files to 1000px on the longest edge. All sub-folders under the selected input folder will be processed. Continue?', false)) {

                    // Root/top-level input folder
                    var imageFolder = Folder.selectDialog('Select the root/top-level folder to process:');
                    // The output folder should NOT be under the same path as the input folder!
                    var outputFolder = Folder.selectDialog("Please select the output folder to save the WebP files to:");
                    // To do: add supporting code to check for this

                    var origDialogs = app.displayDialogs;
                    app.displayDialogs = DialogModes.NO;

                    // Script Execution Timer - Function    
                    var timeDiff = {
                        setStartTime: function () {
                            d = new Date();
                            time = d.getTime();
                        },
                        getDiff: function () {
                            d = new Date();
                            t = d.getTime() - time;
                            time = d.getTime();
                            return t;
                        }
                    };

                    // Script Execution Timer - Start    
                    timeDiff.setStartTime();

                    // Set the input file processing counter
                    var inputFileCounter = 0;
                    // Set the output file processing counter
                    var fileCounter = 0;

                    if (imageFolder != null) processFolder(imageFolder);

                    function processFolder(folder) {
                        // Special thanks to Paul MR for the recursive folder processing code:
                        // photoshopgurus.com/forum/threads/batch-and-subfolders.22134/
                        var fileList = folder.getFiles()
                        for (var i = 0; i < fileList.length; i++) {
                            var file = fileList[i];
                            if (file instanceof File && file.name.match(/\.(webp|tif|tiff|jpg|jpeg|psd|psb|png)$/i)) {

                                open(file);

                                /* Start Main Code Block */

                                // Proportionally fit image to 1000px on the longest edge
                                fitImage(1000, 1000);

                                /////
                                // If the doc isn't in RGB mode
                                if (activeDocument.mode !== DocumentMode.RGB) {

                                    // Convert to sRGB & 8 bpc
                                    activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.changeMode(ChangeMode.RGB);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                                    // If the doc is in RGB mode
                                } else {
                                    // Convert to sRGB & 8 bpc
                                    //activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                                }

                                // Increment the input file saving counter
                                inputFileCounter++

                                /* End Main Code Block */

                            } else
                            if (file instanceof Folder) {
                                processFolder(file);
                            }
                        }
                    }

                    // End of script
                    app.displayDialogs = origDialogs;
                    app.beep();
                    alert('Batch resize and save to WebP completed!' + '\r' + inputFileCounter + ' source files' + '\r' + fileCounter + ' WebP files saved' + '\r' + '(' + timeDiff.getDiff() / 1000 + ' seconds)');
                    // Open the output folder in the Finder or Explorer
                    outputFolder.execute();
                }
            }

        } else {
            alert('Please close all open documents before running this script!');
        }

        ///// FUCTIONS /////

        function fitImage(fWidth, fHeight) {
            /* NEARESTNEIGHBOR | BILINEAR | BICUBIC | BICUBICSMOOTHER | BICUBICSHARPER | BICUBICAUTOMATIC */
            if (activeDocument.height.value > activeDocument.width.value) {
                activeDocument.resizeImage(null, UnitValue(fHeight, "px"), null, ResampleMethod.BICUBIC);
            } else {
                activeDocument.resizeImage(UnitValue(fWidth, "px"), null, null, ResampleMethod.BICUBIC);
            }
        }

        function saveWebP(compType, compValue, xmpData, exifData, psData, asCopy) {
            /*
            v1.1 - 12th March 2023, Stephen Marsh
            https://community.adobe.com/t5/photoshop-ecosystem-discussions/saving-webp-image-by-script/td-p/13642577
            */
            // Doc and path save variables
            var WebPDocName = activeDocument.name.replace(/\.[^\.]+$/, ''); // Remove file extension
            var WebPSavePath = outputFolder + "/" + WebPDocName + ".webp" // Change path as needed
            var WebPFile = new File(WebPSavePath); // Create the file object

            // Check for existing file object
            if (WebPFile.exists) {
                //alert("'" + app.activeDocument.name + "'" + " exists and has been skipped!")
            } else {
                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();

                // Compression parameters = "compressionLossless" | "compressionLossy"
                descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                var WebPCompIsLossless = false; // set the default flag for compression
                if (WebPCompIsLossless == false) {
                    // 0 (lowest lossy quality) - 100 (highest lossy quality)
                    descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                }

                // Metadata options
                descriptor2.putBoolean(s2t("includeXMPData"), xmpData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includeEXIFData"), exifData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includePsExtras"), psData); // Boolean param moved to function call

                // WebP format and save path
                descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
                descriptor.putPath(s2t("in"), WebPFile); // Save path variable

                // Save As = false | Save As a Copy = true
                descriptor.putBoolean(s2t("copy"), asCopy); // Boolean param moved to function call

                // The extension
                descriptor.putBoolean(s2t("lowerCase"), true);

                // Execute the save
                executeAction(s2t("save"), descriptor, DialogModes.NO); // Change NO to ALL for dialog

                // Increment the file saving counter
                fileCounter++;
            }
        }

    }());

 

Stephen Marsh
Community Expert
Community Expert
April 11, 2024

@JonDemand 

 

Try the following script.

 

NOTE: The output folder should not be under the same path as the input folder (otherwise remove webp from the file format name match).

 

As you have requested all files to be saved to a single output folder, you need to consider how to handle duplicate files, as the source folder structure may contain files with the same name as they are in different folders, however, when saved to a single common folder there may be duplicates. This script simply overwrites existing webp files without any alert or logging. You will need to check for missing files yourself, as the input file count may not match the output file count.

 

Batch Save As WebP and Fit Longest Edge to 1000px Wide.jsx

 

/*
Batch Save As WebP and Fit Longest Edge to 1000px Wide.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.0 - 11th April 2024, Stephen Marsh
NOTE:
* The output folder should NOT be under the same path as the input folder
* Existing webp files with duplicate file names in the output folder will be overwritten without warning!
*/

#target photoshop

    (function () {

        if (app.documents.length === 0) {

            // Ensure that version 2022 or later is being used
            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);

            // Fail
            if (versionCheck < 23) {
                alert("You must use Photoshop 2022 or later to save using native WebP format...");
                return;

            // Pass
            } else {

                // Optionally run a specified action
                //var actionName = "Molten Lead"; // Action to run, change as needed
                //var actionSet = "Default Actions"; // Action set to run, change as needed

                if (confirm('This script will proportionally fit all supported files to 1000px on the longest edge. All sub-folders under the selected input folder will be processed. Continue?', false)) {

                    // Root/top-level input folder
                    var imageFolder = Folder.selectDialog('Select the root/top-level folder to process:');
                    // The output folder should NOT be under the same path as the input folder!
                    var outputFolder = Folder.selectDialog("Please select the output folder to save the WebP files to:");
                    // To do: add supporting code to check for this

                    var origDialogs = app.displayDialogs;
                    app.displayDialogs = DialogModes.NO;

                    // Script Execution Timer - Function    
                    var timeDiff = {
                        setStartTime: function () {
                            d = new Date();
                            time = d.getTime();
                        },
                        getDiff: function () {
                            d = new Date();
                            t = d.getTime() - time;
                            time = d.getTime();
                            return t;
                        }
                    };

                    // Script Execution Timer - Start    
                    timeDiff.setStartTime();

                    if (imageFolder != null) processFolder(imageFolder);

                    function processFolder(folder) {
                        // Special thanks to Paul MR for the recursive folder processing code:
                        // photoshopgurus.com/forum/threads/batch-and-subfolders.22134/
                        var fileList = folder.getFiles()
                        for (var i = 0; i < fileList.length; i++) {
                            var file = fileList[i];
                            if (file instanceof File && file.name.match(/\.(webp|tif|tiff|jpg|jpeg|psd|psb|png)$/i)) {

                                open(file);

                                /* Start Main Code Block */

                                // Proportionally fit image to 1000px on the longest edge
                                fitImage(1000, 1000);

                                /////
                                // If the doc isn't in RGB mode
                                if (activeDocument.mode !== DocumentMode.RGB) {

                                    // Convert to sRGB & 8 bpc
                                    activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.changeMode(ChangeMode.RGB);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                                    // If the doc is in RGB mode
                                } else {
                                    // Convert to sRGB & 8 bpc
                                    //activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                                    activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                                    // Run the optional action
                                    //app.doAction(actionName, actionSet);

                                    // Save as a copy and close
                                    saveWebP("compressionLossy", 75, true, true, true, true);
                                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                                }

                                /* End Main Code Block */

                            } else
                            if (file instanceof Folder) {
                                processFolder(file);
                            }
                        }
                    }

                    // End of script
                    app.displayDialogs = origDialogs;
                    app.beep();
                    alert('Batch resize and save to WebP completed!' + '\r' + '(' + timeDiff.getDiff() / 1000 + ' seconds)');
                    // Open the output folder in the Finder or Explorer
                    outputFolder.execute();
                }
            }

        } else {
            alert('Please close all open documents before running this script!');
        }


        ///// FUCTIONS /////

        function fitImage(fWidth, fHeight) {
            /* NEARESTNEIGHBOR | BILINEAR | BICUBIC | BICUBICSMOOTHER | BICUBICSHARPER | BICUBICAUTOMATIC */
            if (activeDocument.height.value > activeDocument.width.value) {
                activeDocument.resizeImage(null, UnitValue(fHeight, "px"), null, ResampleMethod.BICUBIC);
            } else {
                activeDocument.resizeImage(UnitValue(fWidth, "px"), null, null, ResampleMethod.BICUBIC);
            }
        }

        function saveWebP(compType, compValue, xmpData, exifData, psData, asCopy) {
            /*
            v1.1 - 12th March 2023, Stephen Marsh
            https://community.adobe.com/t5/photoshop-ecosystem-discussions/saving-webp-image-by-script/td-p/13642577
            */
            // Doc and path save variables
            var WebPDocName = activeDocument.name.replace(/\.[^\.]+$/, ''); // Remove file extension
            var WebPSavePath = outputFolder + "/" + WebPDocName + ".webp" // Change path as needed
            var WebPFile = new File(WebPSavePath); // Create the file object

                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();

                // Compression parameters = "compressionLossless" | "compressionLossy"
                descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                var WebPCompIsLossless = false; // set the default flag for compression
                if (WebPCompIsLossless == false) {
                    // 0 (lowest lossy quality) - 100 (highest lossy quality)
                    descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                }

                // Metadata options
                descriptor2.putBoolean(s2t("includeXMPData"), xmpData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includeEXIFData"), exifData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includePsExtras"), psData); // Boolean param moved to function call

                // WebP format and save path
                descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
                descriptor.putPath(s2t("in"), WebPFile); // Save path variable

                // Save As = false | Save As a Copy = true
                descriptor.putBoolean(s2t("copy"), asCopy); // Boolean param moved to function call

                // The extension
                descriptor.putBoolean(s2t("lowerCase"), true);

                // Execute the save
                executeAction(s2t("save"), descriptor, DialogModes.NO); // Change NO to ALL for dialog
        }

    }());

 

Stephen Marsh
Community Expert
Community Expert
December 8, 2023

Do you have any 3rd party WebP plugins installed which might be hijacking the save process?

 

This should be using the native Save capability of Photoshop 2022 or higher to save to WebP.

eznewmedia
Participating Frequently
December 8, 2023

Nope .. no plugins installed at all.   And that first script you posted didn't give me any popups, so I wonder what is different??  I see there is a new version of Photoshop (25.2) that I am going to download and install to see if that eliminates the issue ... stay tuned!

 

Stephen Marsh
Community Expert
Community Expert
December 8, 2023

The first version performed a Save As a Copy, enforcing specific WebP compression and metadata parameters, regardless of what may or may not have been in the original files.

 

The second version simply performed a Save.

 

It must be that the WebP files don't have the required metadata in them for Photoshop to know what compression and metadata values to use, so it pops up the dialog for you to specify them. Note to self: Using my own files may not always have the same result, the OP should always provide sample files!

Stephen Marsh
Community Expert
Community Expert
December 7, 2023

@eznewmedia 

 

Try this new 1.1 version based on your feedback:

 

/*
Batch Save As WebP 1000px Wide.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.1 - 8th December 2023, Stephen Marsh
Special thanks to Paul MR for the recursive folder processing code:
photoshopgurus.com/forum/threads/batch-and-subfolders.22134/
*/

#target photoshop

    (function () {

        if (app.documents.length === 0) {

            // Ensure that version 2022 or later is being used
            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);

            // Fail
            if (versionCheck < 23) {
                alert("You must use Photoshop 2022 or later to save using native WebP format...");
                return;

                // Pass
            } else {

                if (confirm('This script will resave all WebP files to 1000px wide. All sub-folders under the selected input folder will be processed. Continue?', false)) {

                    var imageFolder = Folder.selectDialog('Select the top-level folder:');

                    var origDialogs = app.displayDialogs;
                    app.displayDialogs = DialogModes.NO;

                    // Script Execution Timer - Function    
                    var timeDiff = {
                        setStartTime: function () {
                            d = new Date();
                            time = d.getTime();
                        },
                        getDiff: function () {
                            d = new Date();
                            t = d.getTime() - time;
                            time = d.getTime();
                            return t;
                        }
                    };

                    // Script Execution Timer - Start    
                    timeDiff.setStartTime();

                    // Set the file processing counter
                    var fileCounter = 0;

                    if (imageFolder != null) processFolder(imageFolder);

                    function processFolder(folder) {
                        var fileList = folder.getFiles()
                        for (var i = 0; i < fileList.length; i++) {
                            var file = fileList[i];
                            if (file instanceof File && file.name.match(/\.webp/i)) {
                                open(file);
                                // Start Main Code Block
                                activeDocument.resizeImage(UnitValue(1000, "px"), null, null, ResampleMethod.BICUBIC); // width, height, resolution, method
                                activeDocument.close(SaveOptions.SAVECHANGES);
                                fileCounter++;
                                // End Main Code Block
                            } else
                            if (file instanceof Folder) {
                                processFolder(file);
                            }
                        }
                    }

                    // End of script
                    app.displayDialogs = origDialogs;
                    alert('Batch resize and WebP overwrite completed!' + '\r' + fileCounter + ' WebP files processed' + '\r' + '(' + timeDiff.getDiff() / 1000 + ' seconds)');
                }
            }

        } else {
            alert('Please close all open documents before running this script!');
        }
    }());

 

eznewmedia
Participating Frequently
December 8, 2023

Stephen, I tried this script, but it requires clicking "OK" during the save process on each image (just like the two step batch process I first tried).  Your first script actually did NOT require clicking on OK!   I may try to closely example both of the scripts to see I can combine them myself, but I'm attaching a screen grab so you can see what I'm referring to. 

 

BTW, I really appreciate your expertise!   This scripting option is opening all sorts of possibilities to me!

Stephen Marsh
Community Expert
Community Expert
December 8, 2023

I didn't get any popups in the script and I have code in there to turn off dialogs. I didn't get any popups with the action as there are checkboxes in Batch to suppress warnings.

Stephen Marsh
Community Expert
Community Expert
December 7, 2023

@eznewmedia 

 

Try this, it works one top-level/root folder at a time:

 

/*
Batch Save As WebP 1000px Wide.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/looking-for-action-or-script-to-resize-and-save-webp-files/td-p/14282886
v1.0 - 7th December 2023, Stephen Marsh
Based on:
Batch Save As WebP.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/export-many-files-at-once-in-webp-format-photoshop/m-p/13604411
*/

#target photoshop

    (function () {

        // Ensure that version 2022 or later is being used
        var versionNumber = app.version.split(".");
        var versionCheck = parseInt(versionNumber);

        // Fail
        if (versionCheck < 23) {
            alert("You must use Photoshop 2022 or later to save using native WebP format...");
            // Pass

        } else {

            // Set the input and output folders
            var inputFolder = Folder.selectDialog("Please select the input folder:");
            if (inputFolder === null) {
                //alert('Script cancelled!');
                return;
            }

            var outputFolder = Folder.selectDialog("Please select the output folder:");
            if (outputFolder === null) {
                //alert('Script cancelled!');
                return;
            }

            // Limit the input files, add or remove extensions as required
            var fileList = inputFolder.getFiles(/\.(webp|tif|tiff|jpg|jpeg|psd|psb|png)$/i);
            fileList.sort();
            var savedDisplayDialogs = app.displayDialogs;
            app.displayDialogs = DialogModes.NO;

            // Set the file processing counter
            var fileCounter = 0;

            // Process the input files
            for (var i = 0; i < fileList.length; i++) {
                var doc = open(fileList[i]);
                activeDocument.resizeImage(UnitValue(1000, "px"), null, null, ResampleMethod.BICUBIC); // width, height, resolution, method
                saveWebP("compressionLossy", 75, true, true, true, true);
                activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                // Increment the file saving counter
                fileCounter++;
            }

            app.displayDialogs = savedDisplayDialogs;
            alert('Script completed!' + '\n' + fileCounter + ' files saved to:' + '\r' + outputFolder.fsName);


            function saveWebP(compType, compValue, xmpData, exifData, psData, asCopy) {
                /*
                v1.1 - 12th March 2023, Stephen Marsh
                https://community.adobe.com/t5/photoshop-ecosystem-discussions/saving-webp-image-by-script/td-p/13642577
                */
                // Doc and path save variables
                var WebPDocName = activeDocument.name.replace(/\.[^\.]+$/, ''); // Remove file extension
                var WebPSavePath = outputFolder + "/" + WebPDocName + ".webp" // Change path as needed
                var WebPFile = new File(WebPSavePath); // Create the file object

                /*
                // Check for existing file object
                if (WebPFile.exists) {
                    // true = 'No' as default active button
                    if (!confirm("File exists, overwrite: Yes or No?", true))
                        // throw alert("Script cancelled!");
                        throw null;
                }
                */

                function s2t(s) {
                    return app.stringIDToTypeID(s);
                }
                var descriptor = new ActionDescriptor();
                var descriptor2 = new ActionDescriptor();

                // Compression parameters = "compressionLossless" | "compressionLossy"
                descriptor2.putEnumerated(s2t("compression"), s2t("WebPCompression"), s2t(compType)); // string variable
                var WebPCompIsLossless = false; // set the default flag for compression
                if (WebPCompIsLossless == false) {
                    // 0 (lowest lossy quality) - 100 (highest lossy quality)
                    descriptor2.putInteger(s2t("quality"), compValue); //  number variable
                }

                // Metadata options
                descriptor2.putBoolean(s2t("includeXMPData"), xmpData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includeEXIFData"), exifData); // Boolean param moved to function call
                descriptor2.putBoolean(s2t("includePsExtras"), psData); // Boolean param moved to function call

                // WebP format and save path
                descriptor.putObject(s2t("as"), s2t("WebPFormat"), descriptor2);
                descriptor.putPath(s2t("in"), WebPFile); // Save path variable

                // Save As = false | Save As a Copy = true
                descriptor.putBoolean(s2t("copy"), asCopy); // Boolean param moved to function call

                // The extension
                descriptor.putBoolean(s2t("lowerCase"), true);

                // Execute the save
                executeAction(s2t("save"), descriptor, DialogModes.NO); // Change NO to ALL for dialog
            }
        }

    }());

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

 

eznewmedia
Participating Frequently
December 7, 2023

Hi Stephan, this script works really well!  Looking at the programming language, it's very logical and elegant.  It's still somewhat time consuming since it only does a single folder at a time, and so I have to choose the main folder, and then the destination folder for each set of images ... and there are hundreds of folders!  Is it possible to add a function in this script so it behaves like a Photoshop action to select a folder, and then all the subfolders?

 

I also see a "save as" function in the script that looks for existing files, so I'm guessing it might be possible to just have the script overwrite the existing files, or have a "flag" to check an option for overwriting existing files?  For my particular application, I'm working with a copy of the folders and files that I need to convert to smaller WebP images, so just have the script overwrite the existing files if choosing to save back to the original directory would be ideal! 

 

Trying to think through the logic, maybe if a folder is selected, and all of its sub folders are also selected, the script will have a dialogue for a check box to "overwrite existing files?" or something along those lines.  Not even sure if this is possible with scripting, but I thought I'd ask!  I can't wait to try out some of my own scripts ... can you recommend a good resource Stephen?

 

-Jim

Stephen Marsh
Community Expert
Community Expert
December 7, 2023

I can make modifications, however, have you looked at my earlier suggestion of a simple 2 step action run via batch?

Stephen Marsh
Community Expert
Community Expert
December 7, 2023

Yes, I can add the code to my original script. Do you have a preference for the resize interpolation method? What about metadata and quality options?

 

I presume that you don't require colour profile conversions etc.

 

EDIT: It should just be a matter of a simple 2 or 3-step Action to resize and save and possibly close without saving, then running Automate > Batch.