Updating Solid Color adjustment layer color using Photoshop scripting?

Hi,

I am trying to edit one of my scripts with a function that allows the user to edit a solid color fill adjustment layer at the moment the user clicks somewhere using the color picker.

Basically, I tried applying the suggested code in the pickColor( and the updateColorFillLayer functions. Thats where i want to make this code work.

Basically, what i wanted to achieve was for it to target the layer called “color” , open the color editor, and then allowing me to choose the color but to update the solid layer color LIVE. Similar to the experience you get when you click on the solid color adjustment layer thumbnail, that wherever your mouse clicks, it will update the layers colors.

Hope someone can help me troubleshoot this? or too much of an ask lol.

Cheeers!

I was suggested to use this script:

#target photoshop

/*
Interactive Color Fill.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-update-solid-color-adjustment-layer-color-using-photoshop-scripting/td-p/13702428
v1.0 - 4th April 2023, Stephen Marsh
*/

if (app.documents.length > 0) {

    if (activeDocument.activeLayer.kind == LayerKind.SOLIDFILL) {

        interactiveSetColorFill();

    } else {
        alert("The active layer isn't a Color Fill layer!");
    }

} else {
    alert('You must have a document open!');
}


function interactiveSetColorFill() {
    /*
    Get the colour fill RGB values
    https://community.adobe.com/t5/photoshop-ecosystem-discussions/get-current-solid-layer-color-hex-code-in-alert/td-p/10830649
    */
    var r = new ActionReference();
    r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("adjustment"));
    r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
    var objAdjustment = executeActionGet(r).getList(stringIDToTypeID("adjustment"));
    var objsolidColorLayer = objAdjustment.getObjectValue(0);
    var objRGBColor = objsolidColorLayer.getObjectValue(stringIDToTypeID("color"));
    var rValue = Math.round(objRGBColor.getDouble(stringIDToTypeID("red")));
    var gValue = Math.round(objRGBColor.getDouble(stringIDToTypeID("grain")));
    var bValue = Math.round(objRGBColor.getDouble(stringIDToTypeID("blue")));
    /*
    Set the colour fill RGB values
    */
    function s2t(s) {
        return app.stringIDToTypeID(s);
    }
    var descriptor = new ActionDescriptor();
    var descriptor2 = new ActionDescriptor();
    var descriptor3 = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putEnumerated(s2t("contentLayer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor.putReference(s2t("null"), reference);
    descriptor3.putDouble(s2t("red"), rValue);
    descriptor3.putDouble(s2t("grain"), gValue);
    descriptor3.putDouble(s2t("blue"), bValue);
    descriptor2.putObject(s2t("color"), s2t("RGBColor"), descriptor3);
    descriptor.putObject(s2t("to"), s2t("solidColorLayer"), descriptor2);
    executeAction(s2t("set"), descriptor, DialogModes.ALL);
}

:smiley: and My code is the following:

:smiley:

function main() {
    var psdFolder = Folder.selectDialog("Select the folder containing PSD files:");
    var imgFolder = Folder.selectDialog("Select the folder containing image files:");
    var exportFolder = Folder.selectDialog("Select the folder for exported files:");

    if (!psdFolder || !imgFolder || !exportFolder) {
        alert("No folder selected. Exiting...");
        return;
    }

    var psdFiles = psdFolder.getFiles("*.psd");
    var imgFiles = imgFolder.getFiles(/\.(jpg|jpeg|png|tif|tiff|bmp|gif)$/i);

    for (var i = 0; i < psdFiles.length; i++) {
        var psdFile = psdFiles[i];
        var doc = open(psdFile);

        var colorFillLayer = findLayerByName(doc, "color");

        for (var j = 0; j < imgFiles.length; j++) {
            var imgFile = imgFiles[j];

            // Find both smart object layers
            var layerVertical = findLayerByName(doc, "smart_object_vertical");
            var layerSquare = findLayerByName(doc, "smart_object_square");

            // Calculate aspect ratio
            var aspectRatio = getImageAspectRatio(imgFile);

            // Choose the appropriate smart object layer based on the aspect ratio
            var layerName = aspectRatio < 1 ? "smart_object_vertical" : "smart_object_square";

            // Set the visibility of both layers accordingly
            if (layerName === "smart_object_vertical") {
                layerVertical.visible = true;
                layerSquare.visible = false;
            } else {
                layerVertical.visible = false;
                layerSquare.visible = true;
            }

            var layer = findLayerByName(doc, layerName);
            if (layer) {
                replaceSmartObjectContent(doc, layer, imgFile);
            }

            // Pick the color and update the color fill layer
            var pickedColor = pickColor();
            if (pickedColor) {
                updateColorFillLayer(doc, colorFillLayer, pickedColor);
            }

            var fileName = psdFile.name.replace(".psd", "_" + imgFile.name);
            var saveFile = new File(exportFolder + "/" + fileName);

            // Check if the image has been processed already to not process again in the same folder
            if (saveFile.exists) {
                continue;
            }

            setDocumentResolution(doc, 300);
            saveAsPNG(doc, saveFile);
        }

        // Close the document and don't save changes
        doc.close(SaveOptions.DONOTSAVECHANGES);
    }
}

function getImageAspectRatio(file) {
    var tempDoc = open(file);
    var aspectRatio = tempDoc.width / tempDoc.height;
    tempDoc.close(SaveOptions.DONOTSAVECHANGES);
    return aspectRatio;
}

function setDocumentResolution(doc, resolution) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var originalWidth = doc.width;
    var originalHeight = doc.height;
    var resampleMethod = ResampleMethod.AUTOMATIC;
    doc.resizeImage(originalWidth, originalHeight, resolution, resampleMethod);

    app.preferences.rulerUnits = originalRulerUnits;
}


function findLayerByName(doc, name, layerSet) {
    if (!layerSet) layerSet = doc.layers;
    
    for (var i = 0; i < layerSet.length; i++) {
        var layer = layerSet[i];
        if (layer.name === name) {
            return layer;
        }
        if (layer.typename === "LayerSet") {
            var foundLayer = findLayerByName(doc, name, layer.layers);
            if (foundLayer) {
                return foundLayer;
            }
        }
    }
    return null;
}





function updateColorFillLayer(doc, colorFillLayer, fillColor) {
    var activeLayer = doc.activeLayer;
    doc.activeLayer = colorFillLayer;

    function s2t(s) {
        return app.stringIDToTypeID(s);
    }

    

    var descriptor = new ActionDescriptor();
    var descriptor2 = new ActionDescriptor();
    var descriptor3 = new ActionDescriptor();
    var reference = new ActionReference();

    reference.putEnumerated(s2t("contentLayer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor.putReference(s2t("null"), reference);

    descriptor3.putDouble(s2t("red"), fillColor.rgb.red);
    descriptor3.putDouble(s2t("grain"), fillColor.rgb.green);
    descriptor3.putDouble(s2t("blue"), fillColor.rgb.blue);

    descriptor2.putObject(s2t("color"), s2t("RGBColor"), descriptor3);
    descriptor.putObject(s2t("to"), s2t("solidColorLayer"), descriptor2);

    executeAction(s2t("set"), descriptor, DialogModes.NO);

    doc.activeLayer = activeLayer;
}



function saveAsPNG(doc, saveFile) {
var pngOptions = new PNGSaveOptions();
pngOptions.compression = 2; // Change this value to control the compression level (0-9)
pngOptions.interlaced = false;
doc.saveAs(saveFile, pngOptions, true, Extension.LOWERCASE);
}
function replaceSmartObjectContent(doc, layer, imgFile) {
    doc.activeLayer = layer;
    if (layer.kind === LayerKind.SMARTOBJECT) {
        var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
        var desc = new ActionDescriptor();
        desc.putPath(charIDToTypeID("null"), imgFile);
        try {
            executeAction(idplacedLayerReplaceContents, desc, DialogModes.NO);
        } catch (e) {
            alert("Error: " + e.message);
        }
    } else {
        alert("The specified layer is not a Smart Object.");
    }
}


function pickColor() {
    // Check if the active layer is a Solid Color adjustment layer
    if (activeDocument.activeLayer.kind == LayerKind.SOLIDFILL) {
        // Get the current color of the Solid Color adjustment layer
        var currentColor = interactiveSetColorFill();

        // Set the initial color of the color picker to the current color
        app.foregroundColor.rgb.red = currentColor[0];
        app.foregroundColor.rgb.green = currentColor[1];
        app.foregroundColor.rgb.blue = currentColor[2];
    }

    var colorPicker = new Window("dialog", "Choose a color");
    colorPicker.orientation = "column";
    colorPicker.alignChildren = "left";

    var colorPickerPanel = colorPicker.add("panel", undefined, "Color");
    colorPickerPanel.alignment = "fill";
    colorPickerPanel.margins = 10;

    var colorPickerGroup = colorPickerPanel.add("group");
    colorPickerGroup.orientation = "row";
    colorPickerGroup.alignChildren = "center";
    colorPickerGroup.margins = 0;

    colorPickerGroup.add("statictext", undefined, "Current color:");
    var colorSample = colorPickerGroup.add("panel", undefined, "");
    colorSample.size = [40, 20];
    colorSample.graphics.backgroundColor = colorSample.graphics.newBrush(colorSample.graphics.BrushType.SOLID_COLOR, [app.foregroundColor.rgb.red / 255, app.foregroundColor.rgb.green / 255, app.foregroundColor.rgb.blue / 255]);

    colorPicker.add("button", undefined, "Choose color", {name: "ok"});
    colorPicker.add("button", undefined, "Cancel", {name: "cancel"});

    if (colorPicker.show() === 1) {
        app.showColorPicker();
        return app.foregroundColor;
    } else {
        return null;
    }
}
    

/*function pickColor() {
    var colorPicker = new Window("dialog", "Choose a color");
    colorPicker.orientation = "column";
    colorPicker.alignChildren = "left";

    var colorPickerPanel = colorPicker.add("panel", undefined, "Color");
    colorPickerPanel.alignment = "fill";
    colorPickerPanel.margins = 10;

    var colorPickerGroup = colorPickerPanel.add("group");
    colorPickerGroup.orientation = "row";
    colorPickerGroup.alignChildren = "center";
    colorPickerGroup.margins = 0;

    colorPickerGroup.add("statictext", undefined, "Current color:");
    var colorSample = colorPickerGroup.add("panel", undefined, "");
    colorSample.size = [40, 20];
    colorSample.graphics.backgroundColor = colorSample.graphics.newBrush(colorSample.graphics.BrushType.SOLID_COLOR, [app.foregroundColor.rgb.red / 255, app.foregroundColor.rgb.green / 255, app.foregroundColor.rgb.blue / 255]);

    colorPicker.add("button", undefined, "Choose color", {name: "ok"});
    colorPicker.add("button", undefined, "Cancel", {name: "cancel"});

    if (colorPicker.show() === 1) {
        app.showColorPicker();
        return app.foregroundColor;
    } else {
        return null;
    }
}
*/

main();

This is all ExtendScript code which is now obsolete.
Adobe released a new framework called UXP 3 years ago and whilst there is some still legacy support for running ExtendScript it will be phased out.
This forum is for UXP development - I believe there is still an active ExtendScript community on the Adobe Community Forums though.

The best place to start with UXP is Davide Barranca’s excellent series of videos.

I don’t believe so :thinking: Although it’s mostly UXP, but there are quite a few topics on ExtendScript too IIRC. Also, there’s a common Photoshop category and a dedicated UXP API sub-category (although lots of UXP topics are posted in the common category), so I’d assume both UXP and ES topics are valid here. @Erin_Finnegan, could you please express your opinion on this? :slight_smile:

I stand corrected! :person_facepalming:

Thanks everyone for chiming in.
I managed to resolve it.

Quick question though, you did say it will be phased out, so that means that all scripts that do not use the new UXP frameworks or whatever its called, will not work anymore ? :sweat_smile:

Please confirm, thanks!
@Karmalakas @Timothy_Bennett

That is correct - as to when that will happen has not been announced by Adobe yet.
UXP is a bit harder to get to grips with without some basic knowledge of ES6 JavaScript than CEP was, but personally speaking I find it a much more enjoyable and intuitive developer experience.
You should have a look at the Alchemist plugin - its usage is covered in the video series I linked earlier. Alchemist can be used to “record” what you do in Photoshop and will generate code for you.
It also comes with the Sorcerer plugin which can be used in conjunction with Alchemist to generate your own plugins.

1 Like

Wait, yes it is. :sweat_smile:

Although this isn’t necessarily the right place to get ExtendScript advice, this isn’t the wrong place, either.

@Elegante here didn’t even know about UXP or Alchemist, or that, say, scripting is available in modern JavaScript in Photoshop now via UXP scripting. Here is someone who will benefit from migrating… and/or ask a whole lot of questions that other ExtendScript users will also find valuable.

1 Like

To address this question:

I think this user in the community forums is expressing a similar sentiment:

You’ll have a revolt if you kill Extendscript on Photoshop. Oh boy. A LOT of people rely on it in production.

The Photoshop team is aware of this, and therefore, no end date has been given for when ExtendScript-based scripts may stop working.