Set brush opacity?

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

jfriedl

Set brush opacity?

Post by jfriedl »

Hi,
I'd like to set the parameters for when I stroke a path, but I can't figure out how to set the opacity.
When I update the brush size/opacity and look at the log, I see only the size...

Code: Select all    var V1 = new ActionDescriptor();
    var V2 = new ActionReference();
    V2.putEnumerated(charIDToTypeID("Brsh"),charIDToTypeID("Ordn"),charIDToTypeID("Trgt"));
    V1.putReference(charIDToTypeID("null"), V2);
    var V3 = new ActionDescriptor();
    V3.putUnitDouble(stringIDToTypeID("masterDiameter"),charIDToTypeID("#Pxl"), 12.345000);
    V1.putObject(charIDToTypeID("T   "),charIDToTypeID("Brsh"), V3);
    executeAction(charIDToTypeID("setd"), V1, DialogModes.NO)


I also tried stuffing a "masterOpacity" and "Opct" percent into V3, but also to no avail.

Any ideas?
Thanks.

Professional AI Audio Generation within Adobe Premiere Pro - Download Free Plugin here

Mike Hale

Set brush opacity?

Post by Mike Hale »

As far as I know some brush settings like blendmode, opacity, flow, etc. can only be set with brush presets.

You can use action manager to get the currentToolOptions descriptor. The one for brush as about 40 or so keys. Almost all are read only.

Using brush presets is not ideal but it's the best that can be done in scripting. Below is an example to apply an existing preset by name( from unknown author ).

Code: Select all/////////////////////////////////////////////////////////////////////////////
//Usage:-
// selectBrush("Airbrush Pen Opacity Flow" );
// selectBrush("Soft Round 21 pixels" );
/////////////////////////////////////////////////////////////////////////////
function selectBrush(brushName) {
  function cTID(s) { return app.charIDToTypeID(s); };
  function sTID(s) { return app.stringIDToTypeID(s); };
var idslct = charIDToTypeID( "slct" );
    var desc4 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
        var ref2 = new ActionReference();
        var idBrsh = charIDToTypeID( "Brsh" );
        ref2.putName( idBrsh, brushName);
    desc4.putReference( idnull, ref2 );
    executeAction( idslct, desc4, DialogModes.NO );
};
jfriedl

Set brush opacity?

Post by jfriedl »

Thanks Mike, that helps.

By the way, I realize now that when I wrote "opacity", I meant "feather".... it's the feather that I want to adjust.... I don't know why I had "opacity" on the brain, but it doesn't matter because I couldn't get feather/hardness to work either, and so your suggestion for a preset still stands as the best solution.

BTW, it turns out that if you want to set the brush size, you have to actually select the brush tool first; FYI, here are my functions in this area, which I call in turn the first time I need to work with the brush:

Code: Select allfunction SelectBrushTool()
{   
    var V1 = new ActionDescriptor();
    var V2 = new ActionReference();
    V2.putClass(charIDToTypeID("PbTl"));
    V1.putReference(charIDToTypeID("null"), V2);
    executeAction(charIDToTypeID("slct"), V1, DialogModes.NO);
}

function SelectBrushPreset(name)
{   
    var V1 = new ActionDescriptor();
    var V2 = new ActionReference();
    V2.putName(charIDToTypeID("Brsh"), name);
    V1.putReference(charIDToTypeID("null"), V2);
    executeAction(charIDToTypeID("slct"), V1, DialogModes.NO);
}


function SetBrushSize(size)
{   
    var V1 = new ActionDescriptor();
    var V2 = new ActionReference();
    V2.putEnumerated(charIDToTypeID("Brsh"),charIDToTypeID("Ordn"),charIDToTypeID("Trgt"));
    V1.putReference(charIDToTypeID("null"), V2);
    var V3 = new ActionDescriptor();
    V3.putUnitDouble(stringIDToTypeID("masterDiameter"),charIDToTypeID("#Pxl"), size);
    V1.putObject(charIDToTypeID("T   "),charIDToTypeID("Brsh"), V3);
    executeAction(charIDToTypeID("setd"), V1, DialogModes.NO);
}
Mike Hale

Set brush opacity?

Post by Mike Hale »

This function may help. Note it works with computed brushes only. When used on a sampled brush( like splatter ) it reset the brush to computed. Hardness( second argument ) is another word for feather.

Code: Select allfunction setBrushFeatures(Diameter,Hardness,Angle,Roundness,Spacing,Flipy,Flipx) {
   var ref = new ActionReference();
   ref.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
   var appDesc = executeActionGet(ref);
   var toolDesc = appDesc.getObjectValue(stringIDToTypeID('currentToolOptions'));
   var brushDesc = toolDesc.getObjectValue(stringIDToTypeID('brush'));
   if (Diameter == undefined) Diameter = brushDesc.getDouble(stringIDToTypeID('diameter'));
   if (Hardness == undefined) Hardness = brushDesc.getDouble(stringIDToTypeID('hardness'));
   if (Angle == undefined ) Angle = brushDesc.getDouble(stringIDToTypeID('angle'));
   if (Roundness  == undefined) Roundness = brushDesc.getDouble(stringIDToTypeID('roundness'));
   if (Spacing == undefined) Spacing = brushDesc.getDouble(stringIDToTypeID('spacing'));
   if (Flipy == undefined) Flipy = brushDesc.getBoolean(stringIDToTypeID('flipY'));
   if (Flipx == undefined) Flipx = brushDesc.getBoolean(stringIDToTypeID('flipX'));
    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID( "Brsh" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
    desc.putReference( charIDToTypeID( "null" ), ref );
   var desc1 = new ActionDescriptor();
      desc1.putDouble(stringIDToTypeID('diameter'), Diameter);
      desc1.putDouble(stringIDToTypeID('hardness'), Hardness);
      desc1.putDouble(stringIDToTypeID('angle'), Angle);
      desc1.putDouble(stringIDToTypeID('roundness'), Roundness);
      desc1.putDouble(stringIDToTypeID('spacing'), Spacing);
      desc1.putBoolean(stringIDToTypeID('flipY'), Flipy);
      desc1.putBoolean(stringIDToTypeID('flipX'), Flipx);
    desc.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "Brsh" ), desc1 );
   executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}

setBrushFeatures(undefined, 1, 45, 1);
setBrushFeatures(undefined, undefined, 55);
jacobolus

Set brush opacity?

Post by jacobolus »

Has this all changed recently? I see getDouble and putDouble being used here, but I’m pretty sure most of the relevant computed brush options are "unit doubles".
jacobolus

Set brush opacity?

Post by jacobolus »

Here’s a version of this script with a bit clearer an API. Call it like setBrushFeatures({spacing: 10, angle: 95}) or similar. Takes an object with possible options {diameter, hardness, angle, roundness, spacing, interpolation, flipX, flipY}. Assumes that any unit types will be set to the same as the current brush's unit types. Also, does nothing if the current brush is not a 'computed brush'.

Still doesn’t help with the opacity, of course. :/

Code: Select all// Accepts a "features" object as input, with possible parameters:
//     diameter, hardness, angle, roundness, spacing,
//     interpolation, flipX, flipY
//
// Example:
//     setBrushFeatures({diameter: 10, flipX: false, roundness: 50})
function setBrushFeatures(features) {
    var app_ref, prop, tool_opts, brush, possible_features, i, n, prop, id,
        unit_type, brush_ref, set_brush_desc;

    app_ref = new ActionReference();
    app_ref.putEnumerated($s("application"), $s("ordinal"), $s("targetEnum"));

    tool_opts = (app.executeActionGet(app_ref)
                    .getObjectValue($s('currentToolOptions')));
    if (tool_opts.getObjectType($s('brush')) != $s('computedBrush')) {
        return; // If the brush type isn’t "computedBrush", then bail out
    }
    brush = tool_opts.getObjectValue($s('brush'));
   
    possible_features = {
        diameter: 'unit', hardness: 'unit', angle: 'unit', roundness: 'unit',
        spacing: 'unit', interpolation: 'bool', flipX: 'bool', flipY: 'bool'};
   
    for (prop in features) {
        if (prop in possible_features) {
            id = $s(prop);
            if (possible_features[prop] === 'unit') {
                unit_type = brush.getUnitDoubleType(id);
                brush.putUnitDouble(id, unit_type, features[prop]);
            } else if (possible_features[prop] === 'bool') {
                brush.putBoolean(id, features[prop]);
            }
        }
    }

    brush_ref = new ActionReference();
    brush_ref.putEnumerated( $s('brush'), $s('ordinal'), $s('targetEnum'));
   
    set_brush_desc = new ActionDescriptor();
    set_brush_desc.putReference($s('target'), brush_ref);
    set_brush_desc.putObject($s('to'), $s('brush'), brush);
   
    executeAction($s('set'), set_brush_desc, DialogModes.NO);
};
function $s(s) { return app.stringIDToTypeID(s); }; // shortcut

// Copyright (c) 2012 Jacob Rus
Mike Hale

Set brush opacity?

Post by Mike Hale »

jacobolus wrote:Has this all changed recently?

I don't think it has changed. But if you use putDouble instead of putUnitDouble you don't have to worry about the unitType( at least with these kind of keys ).

A comment about the code you posted, because there are so many people here that are new to scripting I would have either added fully commented details about the features object or provided a sample of how to create one and call the function with it. I understand that that is not needed with someone of your experience( they can get that from the code itself ), but I would think that many of our members will not understand how to use your function.
jacobolus

Set brush opacity?

Post by jacobolus »

The getDouble is the one I’m most curious about. Can you always use getDouble when the value is a UnitDouble? I guess I can test this...

Mike Hale wrote:I would have either added fully commented details about the features object or provided a sample of how to create one and call the function with it.
Oh, sorry, I put that in the post, but not directly in with the code. Possible calls:

Code: Select allsetBrushFeatures({spacing: 10, angle: 95})

setBrushFeatures({hardness: 5, diameter: 100})

setBrushFeatures({flipX: false, flipY: true})
Any features you don’t mention will be left as they currently are.
Mike Hale

Set brush opacity?

Post by Mike Hale »

I find it hard to say anything about Action Manager with confidence. And I wouldn't think some of the brush setting would accept any unitType. For example even in the GUI brush size only accepts pixels. I think that if you tried to use a unitType of inch and a unitValue of 1 to set the size it would ignore the unitType and set it to 1 pixel.

I think that for keys that only accept one unitType you can use putDouble instead of putUnitDouble. Either will work, you just don't have to deal with the redundant unitValue when using putUnitDouble.

And this is just my understanding, I could be wrong about some what I said but using putDouble does work with some keys that getter says are unitDouble types.

And to answer your question, no I don't think it would work with all keys that use unitDouble.
jacobolus

Set brush opacity?

Post by jacobolus »

This code is identical to the code up above, but has some explanatory comments interspersed:
Code: Select all// a shortcut for stringIDToTypeID, to save typing
var $s = function (s) { return app.stringIDToTypeID(s); };

// Accepts a "features" object as input, with possible parameters:
//     diameter, hardness, angle, roundness, spacing,
//     interpolation, flipX, flipY
//
// Example:
//     setBrushFeatures({diameter: 10, flipX: false, roundness: 50})
var setBrushFeatures = function (features) {
    var app_ref, prop, tool_opts, brush, possible_features, i, n, prop, id,
        unit_type, brush_ref, set_brush_desc;

    app_ref = new ActionReference();
    app_ref.putEnumerated($s("application"), $s("ordinal"), $s("targetEnum"));

    // get the "type" of the brush, and get the brush's settings. If the type
    // isn’t "computedBrush", then bail out of this function, because there’s
    // no currently known way to set other kinds of brush settings.
    tool_opts = (app.executeActionGet(app_ref)
                    .getObjectValue($s('currentToolOptions')));
    if (tool_opts.getObjectType($s('brush')) != $s('computedBrush')) {return;}
    brush = tool_opts.getObjectValue($s('brush'));
   
    // the list of features we might pass in here.
    possible_features = {
        diameter: 'unit', hardness: 'unit', angle: 'unit', roundness: 'unit',
        spacing: 'unit', interpolation: 'bool', flipX: 'bool', flipY: 'bool'};
   
    // loop through all the features in the passed-in object, and for any
    // of them that match our list of possible features, change that setting
    // in the 'brush' descriptor that we fetched earlier, making sure to
    // set the proper type of value (either "unit double" or "boolean")
    for (prop in features) {
        if (prop in possible_features) {
            id = $s(prop);
            if (possible_features[prop] === 'unit') {
                unit_type = brush.getUnitDoubleType(id);
                brush.putUnitDouble(id, unit_type, features[prop]);
            } else if (possible_features[prop] === 'bool') {
                brush.putBoolean(id, features[prop]);
            }
        }
    }

    // get a reference to the "target" brush (i.e. the current brush)
    brush_ref = new ActionReference();
    brush_ref.putEnumerated( $s('brush'), $s('ordinal'), $s('targetEnum'));
   
    // make an action descriptor for the action, with the target set
    // to the current brush, and the content set to our brush descriptor
    // with our custom settings.
    set_brush_desc = new ActionDescriptor();
    set_brush_desc.putReference($s('target'), brush_ref);
    set_brush_desc.putObject($s('to'), $s('brush'), brush);
   
    executeAction($s('set'), set_brush_desc, DialogModes.NO);
};

// Copyright (c) 2012 Jacob Rus