How to import, modify, and save images with Photoshop JSX script

New Here ,
Jun 24, 2022 Jun 24, 2022

Copy link to clipboard

Copied

Hello,

 

i'm quite new in Photoshop scripting. I would like to make batch images process that will open a new file, import 3 images in overlay mode and add autolevel modifier and save the file. And this for each 3 files in folders in a specific folder.

 

In each "something" folders, i will have :

\something\

  • something_height.png
  • something_normal.png
  • something_roughness.png
  • something_basecolor.png
  • something_occulsion.png

 

My current script is able to search on each folders and subfolders, images wich contains "height", "normal", or "roughness" string and return the path :

 

~/Desktop/export/textures/something/something_height.png (same for normal, and roughness)

~/Desktop/export/textures/something2/something2_height.png (same for normal, and roughness)

~/Desktop/export/textures/something3/something3_height.png (same for normal, and roughness)

 

The script should open height file, than add in overlay normal and roughness file. Add AutoLevel, then save the file to something_final.png

I create and convert Actions to JavaScript (jsx) using xtools script.

Currently, the script shows height, normal, roughness filepath for each "something" folders.

 

Could you help me please ?

 

Have a good day.

 

 

#target photoshop

cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };

// Define Variables
var normalMask = ['Normal|normal|NORM|norm|'];
var heightMask = ['Height|height|DISP|disp|'];
var roughnessMask = ['Roughness|roughness|ROUGH|rough'];

var topFolder = new Folder('C:\\Users\\myaccount\\Desktop\\export\\textures\\');
var normalArray = scanSubFolders(topFolder, normalMask);
var heightArray = scanSubFolders(topFolder, heightMask);
var roughnessArray = scanSubFolders(topFolder, roughnessMask);

var normalPath = normalArray[0];
var heightPath = heightArray[0];
var roughnessPath = roughnessArray[0];


// my_Action
//==================== ScriptAutoLevel ==============
//

//All Height files paths found and amount of files found
alert("Height List: " + heightPath.join('\n') + "\n\n Height File Amount: " + heightPath.length);

for (var a = 0; a < heightPath.length; a++) {

    alert('HeighPath : ' + heightPath[a]);
    alert('normalPath : ' + normalPath[a]);
    alert('roughnessPath : ' + roughnessPath[a]);

    function ScriptAutoLevel() {
    
        // Open
        function step1(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            desc1.putBoolean(sTID("dontRecord"), false);
            desc1.putBoolean(sTID("forceNotify"), true);
            desc1.putPath(cTID('null'), new File(heightPath[a]));
            desc1.putInteger(cTID('DocI'), 238);
            executeAction(cTID('Opn '), desc1, dialogMode);
        };

        // Place
        function step2(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            desc1.putInteger(cTID('Idnt'), 2);
            desc1.putPath(cTID('null'), new File(normalPath[a]));
            desc1.putEnumerated(cTID('FTcs'), cTID('QCSt'), sTID("QCSAverage"));
            var desc2 = new ActionDescriptor();
            desc2.putUnitDouble(cTID('Hrzn'), cTID('#Pxl'), 0);
            desc2.putUnitDouble(cTID('Vrtc'), cTID('#Pxl'), 0);
            desc1.putObject(cTID('Ofst'), cTID('Ofst'), desc2);
            executeAction(cTID('Plc '), desc1, dialogMode);
        };

        // Set
        function step3(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            var ref1 = new ActionReference();
            ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
            desc1.putReference(cTID('null'), ref1);
            var desc2 = new ActionDescriptor();
            desc2.putEnumerated(cTID('Md  '), cTID('BlnM'), cTID('Ovrl'));
            desc1.putObject(cTID('T   '), cTID('Lyr '), desc2);
            executeAction(cTID('setd'), desc1, dialogMode);
        };

        // Place
        function step4(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            desc1.putInteger(cTID('Idnt'), 3);
            desc1.putPath(cTID('null'), new File(roughnessPath[a]));
            desc1.putEnumerated(cTID('FTcs'), cTID('QCSt'), sTID("QCSAverage"));
            var desc2 = new ActionDescriptor();
            desc2.putUnitDouble(cTID('Hrzn'), cTID('#Pxl'), 0);
            desc2.putUnitDouble(cTID('Vrtc'), cTID('#Pxl'), 0);
            desc1.putObject(cTID('Ofst'), cTID('Ofst'), desc2);
            executeAction(cTID('Plc '), desc1, dialogMode);
        };

        // Set
        function step5(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            var ref1 = new ActionReference();
            ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
            desc1.putReference(cTID('null'), ref1);
            var desc2 = new ActionDescriptor();
            desc2.putEnumerated(cTID('Md  '), cTID('BlnM'), cTID('Ovrl'));
            desc1.putObject(cTID('T   '), cTID('Lyr '), desc2);
            executeAction(cTID('setd'), desc1, dialogMode);
        };

        // Make
        function step6(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            var ref1 = new ActionReference();
            ref1.putClass(cTID('AdjL'));
            desc1.putReference(cTID('null'), ref1);
            var desc2 = new ActionDescriptor();
            var desc3 = new ActionDescriptor();
            desc3.putEnumerated(sTID("presetKind"), sTID("presetKindType"), sTID("presetKindDefault"));
            desc2.putObject(cTID('Type'), cTID('Lvls'), desc3);
            desc1.putObject(cTID('Usng'), cTID('AdjL'), desc2);
            executeAction(cTID('Mk  '), desc1, dialogMode);
        };

        // Set
        function step7(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            var ref1 = new ActionReference();
            ref1.putEnumerated(cTID('AdjL'), cTID('Ordn'), cTID('Trgt'));
            desc1.putReference(cTID('null'), ref1);
            var desc2 = new ActionDescriptor();
            var list1 = new ActionList();
            var desc3 = new ActionDescriptor();
            var ref2 = new ActionReference();
            ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Blck'));
            desc3.putReference(cTID('Chnl'), ref2);
            desc3.putBoolean(cTID('Auto'), true);
            list1.putObject(cTID('LvlA'), desc3);
            desc2.putList(cTID('Adjs'), list1);
            desc1.putObject(cTID('T   '), cTID('Lvls'), desc2);
            executeAction(cTID('setd'), desc1, dialogMode);
        };

        // Save
        function step8(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            var desc2 = new ActionDescriptor();
            desc2.putEnumerated(cTID('Mthd'), sTID("PNGMethod"), sTID("quick"));
            desc2.putEnumerated(sTID("PNGInterlaceType"), sTID("PNGInterlaceType"), sTID("PNGInterlaceNone"));
            desc2.putEnumerated(sTID("PNGFilter"), sTID("PNGFilter"), sTID("PNGFilterAdaptive"));
            desc2.putInteger(cTID('Cmpr'), 6);
            desc1.putObject(cTID('As  '), sTID("PNGFormat"), desc2);
            desc1.putPath(cTID('In  '), new File(heightPath[a] + "_Final"));
            desc1.putInteger(cTID('DocI'), 238);
            desc1.putBoolean(cTID('Cpy '), true);
            executeAction(cTID('save'), desc1, dialogMode);
        };

        // Close
        function step9(enabled, withDialog) {
            if (enabled != undefined && !enabled)
                return;
            var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
            var desc1 = new ActionDescriptor();
            desc1.putEnumerated(cTID('Svng'), cTID('YsN '), cTID('N   '));
            desc1.putInteger(cTID('DocI'), 238);
            desc1.putBoolean(sTID("forceNotify"), true);
            executeAction(cTID('Cls '), desc1, dialogMode);
        };

        step1(true, true);      // Open
        step2(true, true);      // Place
        step3(true, true);      // Set
        step4(true, true);      // Place
        step5(true, true);      // Set
        step6(true, true);      // Make
        step7(true, true);      // Set
        step8(true, true);      // Save
        step9(true, true);      // Close
    };
    

}

function scanSubFolders(tFolder, mask) { // folder object, RegExp or string
    var sFolders = [];
    var allFiles = [];

    sFolders[0] = tFolder;
    for (var j = 0; j < sFolders.length; j++) { // loop through folders
        var procFiles = sFolders[j].getFiles();
        for (var i = 0; i < procFiles.length; i++) { // loop through this folder contents
            if (procFiles[i] instanceof File) {
                if (mask == undefined) {
                    allFiles.push(procFiles); // if no search mask collect all files
                }
                if (procFiles[i].fullName.search(mask) != -1) {
                    allFiles.push(procFiles[i]); // otherwise only those that match mask
                }
            }
            else if (procFiles[i] instanceof Folder) {
                sFolders.push(procFiles[i]); // store the subfolder
                scanSubFolders(procFiles[i], mask); // search the subfolder
            }
        }
    }
    return [allFiles, sFolders];
}

// EOF

"myScript.jsx"
// EOF

 

 

TOPICS
Actions and scripting , Windows

Views

26

Likes

Translate

Translate

Report

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
no replies

Have something to add?

Join the conversation