What's new
Photoshop Gurus Forum

Welcome to Photoshop Gurus forum. Register a free account today to become a member! It's completely free. Once signed in, you'll enjoy an ad-free experience and be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Where to begin with PS scripting for noob?


PutinHuilo

Well-Known Member
Messages
65
Likes
0
I was using in the past Xtools that creates XML file out of action script, it was a nightmare so i quickly lost interest to it. Now i see on the adobe forum they suggest to use JavaScript, but i have no clue how to integrate it into my action?

Tried searching the net on any guidance and there's ton of information most of outdated from back in the day when they had ExtendScript Toolkit that's removed long time ago.

Tried ScriptListener.8li, but it creates one big log of all actions i done in Photoshop, but only the actions and after finding part i used to record action it was not able to run it saying can't run command "Unknown" might not be in this version of Photoshop etc.

Basically what i am trying to do is to add title to the image using text tool so i loaded into stack 10 images each has name inside layer name.
Need to copy layer name (remove .jpg extension) and use whatever text left for text tool that and place the text in lower right corner of image and then save each layer as that layer_name.jpg
Some working JS examples that copy layer name on adobe forum, but no idea how to use them with my action.

Need some video tutorials about the overall process of using JS to extend my scripts.
 

PRESTON

Well-Known Member
Messages
185
Likes
162
Unfortunately, what you ask is not easy to achieve and requires hours of work from a professional,
now the old javascript is about to be abandoned for the new language called uxp and it is even more complicated to do,
See if there's anyone on the forum who does it for free but I doubt you'll find one.
 

PutinHuilo

Well-Known Member
Messages
65
Likes
0
Unfortunately, what you ask is not easy to achieve and requires hours of work from a professional,
now the old javascript is about to be abandoned for the new language called uxp and it is even more complicated to do,
See if there's anyone on the forum who does it for free but I doubt you'll find one.
I do know how to use JavaScript my question was how to integrate it in photoshop workflow of making actions (macros)?
 

[ iLLuSioN ]

Power User
Messages
382
Likes
396
Save the script (*.jsx) in the scripts folder of photoshop.

To insert the script into your action, you have to start recording at the corresponding point in your action and call up the "insert menu item" command at the top right of the action palette. A dialog box will appear. Now select your script via “File>Scripts>Name of your script” and confirm the dialog box with the OK-button.

Stop recording of the action.
 

MarshySwamp

Active Member
Messages
34
Likes
10
Need some video tutorials about the overall process of using JS to extend my scripts.

Unless you're French, Actions and Scripts are two different things. Even if you are French, they are still two separate things, even if they share the same name! :]

Although it is possible to record the execution of a script into an action to perform a task that is outside the scope of actions, generally one would create the script to replace an action entirely.


Basically what i am trying to do is to add title to the image using text tool... Need to copy layer name (remove .jpg extension) and use whatever text left for text tool that and place the text in lower right corner of image and then save each layer as that layer_name.jpg

Although this is possible and "common enough" to do in Photoshop with the right knowledge and skills, it may be easier to use different software if you have no other interest in learning either legacy ExtendScript language or the new UXP language JavaScript.


2024-01-26_12-17-06.png
 

MarshySwamp

Active Member
Messages
34
Likes
10
As an example, the following script will add the filename to a single document. One can then record the execution of the script into an action, then use File > Automate > Batch or use the Image Processor or Image Processor Pro or other batch scripts to run the action and save the file to various file formats.

Further code could be added to batch process multiple selected files, or a folder and save to a required file format/options so that there is no need to record the script into an action and use batch.

JavaScript:
// Save the original dialog display
var originalDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;

// Save the original ruler units
var originalRulerUnits = app.preferences.rulerUnits;

// Set the working units to px
app.preferences.rulerUnits = Units.PIXELS;

// Create the text layer
app.activeDocument.artLayers.add().kind = LayerKind.TEXT;

// Optionally set the layer to difference blend mode
//app.activeDocument.activeLayer.blendMode = BlendMode.DIFFERENCE;

// Set the text content to the document name without filename extension
(theText = app.activeDocument.activeLayer.textItem).contents = app.activeDocument.name.replace(/\.[^\.]+$/, '');

// Set the text variables
theText.position = [85, 140];
var theColour = new SolidColor();
theColour.rgb.red = 255;
theColour.rgb.green = 255;
theColour.rgb.blue = 255;
theText.color = theColour;
//theText.font = 'Times-Italic';
theText.font = 'ArialMT';
theText.size = 20;
//var textSize = app.activeDocument.height / 100 * 5 * 72 / app.activeDocument.resolution;
//theText.size = textSize;

// Move the text to the lower right, offset by 50px
app.activeDocument.selection.selectAll();
alignToSel('AdRg');
alignToSel('AdBt');
app.activeDocument.activeLayer.translate(-50, -50);
app.activeDocument.selection.deselect();

// Reset the original application settings
app.preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;


// Functions
function alignToSel(method) {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    desc.putReference(charIDToTypeID("null"), ref);
    desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
    try {
        executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
    } catch (e) {}
}


 

MarshySwamp

Active Member
Messages
34
Likes
10
Now i see on the adobe forum they suggest to use JavaScript, but i have no clue how to integrate it into my action?

If the script is installed in the program folder presets/scripts folder, then it will be available under File > Scripts when you record the action.

If the script file is located elsewhere, record the action and use File > Scripts > Browse to record the execution of the script.


Tried searching the net on any guidance and there's ton of information most of outdated from back in the day when they had ExtendScript Toolkit that's removed long time ago.

ExtendScript Toolkit is a 32-bit application, so it doesn't work on modern Mac OS systems, but it can still be used in Windows.

Adobe recommends the use of Visual Studio Code + Adobe ExtendScript Debugger as an IDE for legacy ExtendScript (JavaScript) code.

That being said, one can use any plain text editor (not RTF or word processors) to code the ExtendScript language.


Tried ScriptListener.8li, but it creates one big log of all actions i done in Photoshop, but only the actions and after finding part i used to record action it was not able to run it saying can't run command "Unknown" might not be in this version of Photoshop etc.

It is best to clear the log, run a single command step in Photoshop, and then copy the appropriate block of code generated by the plugin. Many unnecessary steps are often recorded by the plugin and it helps if one has some knowledge of coding to successfully use the code. The code generated by the plugin is known as "Action Manager" or AM code, which is basic low-level ExtendScript code used by Photoshop when various steps are executed.

AM code and the standard Document Object Model or DOM code can be combined and can co-exist in the same .jsx file.


An example of DOM code to add a new standard layer:

JavaScript:
app.activeDocument.artLayers.add();


An example of raw AM code to add a new standard layer, recorded by ScriptingListener:

JavaScript:
var idmake = stringIDToTypeID( "make" );
    var desc8383 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref740 = new ActionReference();
        var idlayer = stringIDToTypeID( "layer" );
        ref740.putClass( idlayer );
    desc8383.putReference( idnull, ref740 );
    var idlayerID = stringIDToTypeID( "layerID" );
    desc8383.putInteger( idlayerID, 119 );
executeAction( idmake, desc8383, DialogModes.NO );


This raw AM code recording can be refactored (reformatted) and somewhat simplified:

JavaScript:
function s2t(s) {
    return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putClass( s2t( "layer" ));
descriptor.putReference( s2t( "null" ), reference );
executeAction( s2t( "make" ), descriptor, DialogModes.NO );


The Photoshop DOM has many missing commands/operations. This is why one must use AM code to do things that would otherwise not be possible.
 
Last edited:

MarshySwamp

Active Member
Messages
34
Likes
10
now the old javascript is about to be abandoned for the new language called uxp and it is even more complicated to do

Adding to this, there currently is and will be some future overlap in time where the old ExtendScript will still be workable, however, the writing is indeed on the wall and UXP is the new heir to the throne. At some future point in time, Photoshop will not support both methods and only UXP will work. When ExtendScript will no longer work has not yet been announced.

UXP is a work in progress and not as mature as ExtendScript, however, it does show promise as a modern language replacement that can interact with other modern systems. I am waiting for UXP to mature, so I will continue to script in legacy ExtendScript before I am forced to use UXP when it becomes unsupported.

UXP is often mentioned in the context of graphic user interface panels, however, it can also create simpler scripts which use the .psjs extension, rather than the legacy ExtendScript .jsx extension. It isn't possible to combine both legacy ExtendScript code and UXP code in the same script.
 
Last edited:

MarshySwamp

Active Member
Messages
34
Likes
10
Here is an example of a self-contained script that will save JPEG files with the file name in the lower right from selected input files. A sub-directory will be created titled "Filename Added" to ensure that the original files with the same name are not overwritten.

JavaScript:
#target photoshop

// Save the original dialog display
var originalDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;

// Save the original ruler units
var originalRulerUnits = app.preferences.rulerUnits;

// Set the working units to px
app.preferences.rulerUnits = Units.PIXELS;

var selectFiles = File.openDialog("Select the input files:", Multiselect = true);
var outputFolder = Folder.selectDialog("Select the save folder:");
outputFolder = new Folder(decodeURI(outputFolder) + '/Filename Added');
if (outputFolder.exists == false) outputFolder.create();

// Set the file processing counter to zero
var counter = 0;

for (var i = 0; i < selectFiles.length; i++) {

    open(selectFiles[i]);

    // Create the text layer
    app.activeDocument.artLayers.add();
    app.activeDocument.activeLayer.kind = LayerKind.TEXT;

    // Optionally set the layer to difference blend mode
    //app.activeDocument.activeLayer.blendMode = BlendMode.DIFFERENCE;

    // Set the text content to the document name without filename extension
    var theText = app.activeDocument.activeLayer.textItem;
    theText.contents = app.activeDocument.name.replace(/\.[^\.]+$/, '');

    // Set the text variables
    theText.position = [85, 140];
    var theColour = new SolidColor();
    theColour.rgb.red = 255;
    theColour.rgb.green = 255;
    theColour.rgb.blue = 255;
    theText.color = theColour;
    //theText.font = 'Times-Italic';
    theText.font = 'ArialMT';
    //theText.size = 20;
    // Set text height to 5% of the doc height
    var textSize = app.activeDocument.height / 100 * 5 * 72 / app.activeDocument.resolution;
    theText.size = textSize;

    // Move the text to the lower right, offset by the text height x2
    app.activeDocument.selection.selectAll();
    alignToSel('AdRg');
    alignToSel('AdBt');
    app.activeDocument.activeLayer.translate(-textSize.value * 2, -textSize.value * 2);
    app.activeDocument.selection.deselect();

    // Save
    var saveJPEGName = File(outputFolder + "/" + theText.contents + ".jpg");
    saveJPEG(saveJPEGName);
    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

    // Increment the file processing counter
    counter++;

}

// Reset the original application settings
app.preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;

// End of script notification
alert("Script completed!" + "\r" + "Files selected: " + selectFiles.length + "\r" + "Files processed: " + counter);


// Functions

function alignToSel(method) {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    desc.putReference(charIDToTypeID("null"), ref);
    desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
    try {
        executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
    } catch (e) {}
}

function saveJPEG(saveFile) {
    var jpgOptns = new JPEGSaveOptions();
    jpgOptns.formatOptions = FormatOptions.STANDARDBASELINE;
    jpgOptns.embedColorProfile = true;
    jpgOptns.quality = 10; // 0 - 12
    activeDocument.saveAs(saveFile, jpgOptns, true, Extension.LOWERCASE);
}
 
Last edited:

Top