Script to change specific color in multiple layers to a new color

Explorer ,
May 27, 2021 May 27, 2021

Copy link to clipboard

Copied

I have a photoshop file with dozens of folders each containing dozens of layers. Many of those layers are toggled as invisible.

 

Throughout all of those layers I need to change the color #eb2121 to the color #87ea76. 

 

Currently I am doing this manually:

1. Opening each folder,

2. Toggling the visibility of each layer,

3. Clicking on each layer one by one and using the paint bucket tool to change the incorrect color to the correct color whenever I see it.

4. Re-toggling the visibility of the layers

5. closing the folder

 

I believe I need a script that will be able to cycle through all layers, locate instannces of the relevant colors and change the color to the new color. Preferably, the script would leave the layers' visibility status and folder open status unchanged.

 

Is anyone aware of such a script?

 

Thank you for your assistance.

TOPICS
Actions and scripting, How to, Mac

Views

458

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
Adobe Community Professional ,
May 27, 2021 May 27, 2021

Copy link to clipboard

Copied

del

...

 

 

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
Adobe Community Professional ,
May 28, 2021 May 28, 2021

Copy link to clipboard

Copied

Could you please provide a sample file where you need to change the color eb2121, but not change the color, say eb2122. First of all, the quality of the "replacement" is of interest.

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
Explorer ,
Jun 08, 2021 Jun 08, 2021

Copy link to clipboard

Copied

Hi r-bin,

Sorry for the delayed response.

 

This is a cartoon character that i'm using for Adobe Character Animator, so the layout, formating and visibility toggling is done to comply with those guidelines. For the character to work in Character Animator, it needs to have the Front body toggled visible, with the Right Profile and Left Profile versions of the boddy toggled invisible.

 

For the attached cartoon character's body, I have multiple layers within folders. I would love to change the character's shirt color, pants color, skin color and hair color, which all appear in multiple layers.

 

Currently, if I wanted to change the character's shirt, I would need to open each layer that contains a sleeve or his torso and manually change the color from say a #666666 grey to a #e84521 orange, which is very long and tedious. Likewise, to change the skin color of the character would take dozens of layers.

 

Ideally, there would be a script that would go through each layer, identify all the pixels that are colored #666666 and change them to color #e84521, while leaving the visibility status unchanged. That would effectively change all the layers containing the character's grey shirt color into an orange shirt. I believe the accuracy of the color change is important.

 

Do you think that is possible?

 

Thank you

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
Adobe Community Professional ,
Jun 08, 2021 Jun 08, 2021

Copy link to clipboard

Copied

LATEST

Well, check out this script.

After calling the script, two ColoPickers will be called. The first sets the starting color, the second sets the ending color.

 

Feature: the pixel at the coordinate (0,0) must be empty on all layers, otherwise it will be corrupted (deleted).

 

The script does not work very fast, but faster than you can do it by hand. At the end, all folders will be collapsed, there is no other option, at least in PS2020.

 

try {
    var tolerance = 32; // for magicwand/bucket

    if (app.showColorPicker(true))
        {
        var c1 = app.foregroundColor;

        if (app.showColorPicker(false))
            {            
            var c2 = app.backgroundColor;

            var old_units = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.PIXELS;

            var total;

            app.displayDialogs = DialogModes.NO;
            set_performance("accelerated");

            app.refresh();

            app.activeDocument.suspendHistory("Replace Color", 'app.doForcedProgress("Replace Color", "total=f()")');

            app.preferences.rulerUnits = old_units;

            alert(total + " layers have been changed"); 
            }
        }
    }
catch (e) { alert(e); }

function f()
    {
    try {
        var total = 0;
        
        var r = new ActionReference();    
        r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        var d = executeActionGet(r)

        var n = d.getInteger(stringIDToTypeID("numberOfLayers"));
        var i0 = d.getBoolean(stringIDToTypeID("hasBackgroundLayer"))?0:1;

        for (var i = i0; i <= n; i++)
            {
            if (!app.updateProgress(i, n)) return;
            app.changeProgressText("Processed: " + i + " of " + n + ",  replaced: " + total);

            var r = new ActionReference();
            r.putIndex(stringIDToTypeID("layer"), i);
            var d = executeActionGet(r);

            if (d.getInteger(stringIDToTypeID("layerKind")) != 1) continue;

            var viz = d.getBoolean(stringIDToTypeID("visible"));

            var r = new ActionReference();
            r.putIndex(stringIDToTypeID("layer"), i);

            var d = new ActionDescriptor();
            d.putBoolean(stringIDToTypeID("makeVisible"), true);
            d.putReference(stringIDToTypeID("null"), r);

            executeAction(stringIDToTypeID("select"), d, DialogModes.NO);

            if (replace_color(c1, c2, tolerance)) ++total;

            if (!viz) 
                {
                var r = new ActionReference();
                r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
                var d = new ActionDescriptor();
                d.putReference(stringIDToTypeID("null"), r);
                executeAction(stringIDToTypeID("hide"), d, DialogModes.NO); 
                }
            }

        executeAction(stringIDToTypeID("collapseAllGroupsEvent"), undefined, DialogModes.NO);

        return total;
        }
    catch (e) { throw(e); }
    }

function replace_color(c1, c2, t)
    {
    try {
        if (t == undefined) t = 32;
    
        var ret = false;

        var doc = app.activeDocument;
        doc.selection.select([[0,0],[0,1],[1,1],[1,0]]);

        fill(c1);

        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
        d.putReference(stringIDToTypeID("null"), r);
        var d1 = new ActionDescriptor();
        d1.putUnitDouble(stringIDToTypeID("horizontal"), stringIDToTypeID("pixelsUnit"), 0);
        d1.putUnitDouble(stringIDToTypeID("vertical"),   stringIDToTypeID("pixelsUnit"), 0);
        d.putObject(stringIDToTypeID("to"), stringIDToTypeID("point"), d1);
        d.putInteger(stringIDToTypeID("tolerance"), t);
        d.putBoolean(stringIDToTypeID("antiAlias"), true);
        d.putBoolean(stringIDToTypeID("merged"), false);
        d.putBoolean(stringIDToTypeID("contiguous"), false);
        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
        
        if (doc.selection.bounds[2].value != 1 || doc.selection.bounds[3].value != 1)
            {
            fill(c2);

            var doc = app.activeDocument;
            doc.selection.select([[0,0],[0,1],[1,1],[1,0]]);

            ret = true;
            }

        executeAction(stringIDToTypeID("delete"), undefined, DialogModes.NO);

        doc.selection.deselect();

        return ret;
        }
    catch (e) { throw(e); }
    }

function fill(c)
    {
    try {
        var red = c.rgb.red - 0.001;
        if (red < 0) red = 0;
        var green = c.rgb.green - 0.001;
        if (green < 0) green = 0;
        var blue = c.rgb.blue - 0.001;
        if (blue < 0) blue = 0;
        var d = new ActionDescriptor();
        d.putEnumerated(stringIDToTypeID("using"), stringIDToTypeID("fillContents"), stringIDToTypeID("color"));
        var d1 = new ActionDescriptor();
        d1.putDouble(stringIDToTypeID("red"),   red);
        d1.putDouble(stringIDToTypeID("green"), green);
        d1.putDouble(stringIDToTypeID("blue"),  blue);
        d.putObject(stringIDToTypeID("color"), stringIDToTypeID("RGBColor"), d1);
        d.putUnitDouble(stringIDToTypeID("opacity"), stringIDToTypeID("percentUnit"), 100);
        d.putEnumerated(stringIDToTypeID("mode"), stringIDToTypeID("blendMode"), stringIDToTypeID("normal"));
        executeAction(stringIDToTypeID("fill"), d, DialogModes.NO);
        }
    catch (e) { throw(e); }
    }

function set_performance(mode)
    {
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("playbackOptions"));
        r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        d.putReference(stringIDToTypeID("null"), r);
        var d1 = new ActionDescriptor();
        d1.putEnumerated(stringIDToTypeID("performance"), stringIDToTypeID("performance"), stringIDToTypeID(mode));
        d.putObject(stringIDToTypeID("to"), stringIDToTypeID("playbackOptions"), d1);
        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
        }
    catch (e) { throw(e); }
    }

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