1

I am totally new in Photoshop scripting, but I have some JavaScript experience.

I want to make a script (or find an existing one and study it) that finds every shape with a specific fill color in my Photoshop project and replaces it with an other one. But I have no idea where to start.

2

Normally you'd expect a script for this to be something like

activeDocument.layers.forEach(function(el) {
    if (el.fillColor == oldColor) el.fillColor = newColor
});

I welcome you to a world of Photoshop Scripting: a world of pain and suffering. While there's a certain number of things you can achieve using Photoshop DOM, a lot of functions and properties are only a available as Action Manager code, used to drive Photoshop at a lower level.

So while the algorithm stays the same — I look for the shape layers with a particular color and then change it — the code may look a little confusing.

var layers = getAllShapeLayersData(),
    sourceColor = [255, 0, 255], // color to look for
    targetColor = [128, 128, 128]; // color to change to

// creating a native Photoshop color object to compare hex values instead of RGBs
var colorToChange = new SolidColor();
colorToChange.rgb.red = sourceColor[0];
colorToChange.rgb.green = sourceColor[1];
colorToChange.rgb.blue = sourceColor[2];

// for all found layers
for (var i = 0; i < layers.length; i++)
{
    // if the shape fill color hex value is the same as source color
    if (layers[i].color.rgb.hexValue == colorToChange.rgb.hexValue)
    {
        // select it first
        selectById(layers[i].id);
        //apply a different color
        changeShapeColor(targetColor);
    }
}

function getAllShapeLayersData()
{
    var lyrs = [];
    try
    {
        activeDocument.backgroundLayer;
        var layers = 0
    }
    catch (e)
    {
        var layers = 1;
    };
    while (true)
    {
        ref = new ActionReference();
        ref.putIndex(charIDToTypeID('Lyr '), layers);
        try
        {
            var desc = executeActionGet(ref);
        }
        catch (err)
        {
            break;
        }

        var lyr = {};
        lyr.type = desc.getInteger(stringIDToTypeID("layerKind"));
        lyr.name = desc.getString(charIDToTypeID("Nm  "));
        lyr.id = desc.getInteger(stringIDToTypeID("layerID"));

        if (lyr.type == 4) // shape layer
        {
            var adj = desc.getList(stringIDToTypeID("adjustment")).getObjectValue(0);

            if (adj.hasKey(stringIDToTypeID("color")))
            {
                var curColor = new SolidColor();
                curColor.rgb.red = adj.getObjectValue(stringIDToTypeID("color")).getUnitDoubleValue(stringIDToTypeID("red"));
                curColor.rgb.green = adj.getObjectValue(stringIDToTypeID("color")).getUnitDoubleValue(stringIDToTypeID("grain"));
                curColor.rgb.blue = adj.getObjectValue(stringIDToTypeID("color")).getUnitDoubleValue(stringIDToTypeID("blue"));
                lyr.color = curColor;
                lyrs.push(lyr);
            }


        }


        layers++;
    }
    return lyrs
}; // end of getAllLayersData()

function changeShapeColor(color)
{
    var desc8 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated(stringIDToTypeID('contentLayer'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
    desc8.putReference(charIDToTypeID('null'), ref1);
    var desc9 = new ActionDescriptor();
    var desc10 = new ActionDescriptor();
    desc10.putDouble(charIDToTypeID('Rd  '), color[0]);
    desc10.putDouble(charIDToTypeID('Grn '), color[1]);
    desc10.putDouble(charIDToTypeID('Bl  '), color[2]);
    desc9.putObject(charIDToTypeID('Clr '), charIDToTypeID('RGBC'), desc10);
    desc8.putObject(charIDToTypeID('T   '), stringIDToTypeID('solidColorLayer'), desc9);
    executeAction(charIDToTypeID('setd'), desc8, DialogModes.NO);
}; // end of changeShapeColor()

function selectById(id)
{
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putIdentifier(charIDToTypeID('Lyr '), id);
    desc1.putReference(charIDToTypeID('null'), ref1);
    executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
}; // end of selectById()
  • 1
    You dont call the API a DOM in photoshop. Its sort of Web only moniker. It would need to give you access to all data to be a DOM but it is not. – joojaa Jun 23 at 15:31
  • 1
    Photoshop Scripting Reference calls Javascript API a Photoshop DOM (page 32), but I know nothing about the names and terms, you might be right – Sergey Kritskiy Jun 23 at 20:02
  • 1
    I'd recommend Davide Barranca's book on Photoshop scripting — that's the only comprehensive source on the subject known to me, including the Photoshop voodoo — ActionManager code. ps-scripting.com And yes, if you don't know what AM is all about 90% of this code look like nonsense, but with time you start to see patterns. It's almost like Neo looking at the Matrix but less cool – Sergey Kritskiy Jun 24 at 7:25
  • 1
    From experience :D Simply run the script on a document with different layer types and write down all the types. Smart Objects are 7 if I'm not mistaken – Sergey Kritskiy Jun 27 at 8:15
  • 1
    what do you mean? if you don't care about layer kind simply don't use it in a condition – Sergey Kritskiy Jun 27 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.