Skip to main content
Participant
June 24, 2022
Question

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

  • June 24, 2022
  • 0 replies
  • 325 views

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

 

 

This topic has been closed for replies.