• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Programmatically convert shape layer to masked color fill layer

Explorer ,
Apr 05, 2024 Apr 05, 2024

Copy link to clipboard

Copied

I'm looking for a scripting or actions wizard—

 

I have an illustration workflow that involves making a drawing in Illustrator and then pasting into Photoshop as many different shape layers. Then I convert these shape layers into masked color fill layers. The whole point of this workflow is being able to use Photoshop filters on the masks to rough up the edges of the shape. This workflow works great for me.  

 

BUT the process of manually converting each shape layer into a masked color fill layer is a little tedious. What's tricky is that the color fill layer needs to retain the color of the shape layer.

 

I can use shortcuts and actions to speed this up a little, but it quickly gets unwieldy if I have more than a few dozen layers.

 

Surely there's some way to automate this?

 

Here's a screencapture of me doing it manually:

1.gif

TOPICS
Actions and scripting , macOS

Views

241

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

correct answers 2 Correct answers

People's Champ , Apr 05, 2024 Apr 05, 2024
Logically, you want to convert the vector mask to a regular one. Try this script for the active shape layer.
 

 

 

try {

// vector masrk to selection (antialias, feather 0)

var d = new ActionDescriptor();  
var r = new ActionReference();  
r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));  
d.putReference(stringIDToTypeID("null"), r);  
var r1 = new ActionReference();  
r1.putEnumerated(stringIDToTypeID("path"), stringIDToTypeID("path"), stringIDToTypeID("vectorMask"));
r1
...

Votes

Translate

Translate
Community Expert , Apr 06, 2024 Apr 06, 2024

Not elegant, but I wonder whether existing Layer Masks may merit consideration.

Edited: updated to the code to exclude Shape Layers with Strokes

Screenshot 2024-04-06 at 13.27.34.pngScreenshot 2024-04-06 at 13.27.43.png

 

 

// change shape layer vector masks to layer masks;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectShapeLayers();
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// process layers;
for (var m = 0; m < theLayers.length; m++) {
// if layer has no stroke;
if (theL
...

Votes

Translate

Translate
Adobe
People's Champ ,
Apr 05, 2024 Apr 05, 2024

Copy link to clipboard

Copied

Logically, you want to convert the vector mask to a regular one. Try this script for the active shape layer.
 

 

 

try {

// vector masrk to selection (antialias, feather 0)

var d = new ActionDescriptor();  
var r = new ActionReference();  
r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));  
d.putReference(stringIDToTypeID("null"), r);  
var r1 = new ActionReference();  
r1.putEnumerated(stringIDToTypeID("path"), stringIDToTypeID("path"), stringIDToTypeID("vectorMask"));
r1.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("to"), r1);  
d.putBoolean(stringIDToTypeID("antiAlias"), true);  
d.putUnitDouble(stringIDToTypeID("feather"), stringIDToTypeID("pixelsUnit"), 0);  
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);  


// create pixel mask from selection 

var d = new ActionDescriptor();
d.putClass(stringIDToTypeID("new"), stringIDToTypeID("channel"));
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("mask"));
d.putReference(stringIDToTypeID("at"), r);
d.putEnumerated(stringIDToTypeID("using"), stringIDToTypeID("userMaskOptions"), stringIDToTypeID("revealSelection"));
executeAction(stringIDToTypeID("make"), d, DialogModes.NO);


// delete current vector mask

var d = new ActionDescriptor();
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("path"), stringIDToTypeID("path"), stringIDToTypeID("vectorMask"));
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d.putReference(stringIDToTypeID("null"), r);
executeAction(stringIDToTypeID("delete"), d, DialogModes.NO);


} catch (e) { alert(e.line+ "\n\n" +e); }

 

 

Votes

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 ,
Apr 06, 2024 Apr 06, 2024

Copy link to clipboard

Copied

😍 Wow, amazing! This works perfectly. I literally gasped and laughed out loud. This will save me so much time! Thank you, kind internet stranger!

Votes

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
Community Expert ,
Apr 06, 2024 Apr 06, 2024

Copy link to clipboard

Copied

Not elegant, but I wonder whether existing Layer Masks may merit consideration.

Edited: updated to the code to exclude Shape Layers with Strokes

Screenshot 2024-04-06 at 13.27.34.pngScreenshot 2024-04-06 at 13.27.43.png

 

 

// change shape layer vector masks to layer masks;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectShapeLayers();
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// process layers;
for (var m = 0; m < theLayers.length; m++) {
// if layer has no stroke;
if (theLayers[m][3] == false) {
selectLayerByID(theLayers[m][1], false);
// load as selection, apply as mask and delete vector mask;
var idchannel = stringIDToTypeID( "channel" );
var idpath = stringIDToTypeID( "path" );
var idnull = stringIDToTypeID( "null" );
var idvectorMask = stringIDToTypeID( "vectorMask" );
// =======================================================
    var desc5 = new ActionDescriptor();
        var ref1 = new ActionReference();
        ref1.putProperty( idchannel, stringIDToTypeID( "selection" ) );
    desc5.putReference( idnull, ref1 );
        var ref2 = new ActionReference();
        ref2.putEnumerated( idpath, idpath, idvectorMask );
        ref2.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
    desc5.putReference( stringIDToTypeID( "to" ), ref2 );
    desc5.putInteger( stringIDToTypeID( "version" ), 1 );
    desc5.putBoolean( stringIDToTypeID( "vectorMaskParams" ), true );
executeAction( stringIDToTypeID( "set" ), desc5, DialogModes.NO );
if (theLayers[m][2] == false) {
    var desc7 = new ActionDescriptor();
    desc7.putClass( stringIDToTypeID( "new" ), idchannel );
        var ref3 = new ActionReference();
        var idmask = stringIDToTypeID( "mask" );
        ref3.putEnumerated( idchannel, idchannel, idmask );
    desc7.putReference( stringIDToTypeID( "at" ), ref3 );
    desc7.putEnumerated( stringIDToTypeID( "using" ), stringIDToTypeID( "userMaskEnabled" ), stringIDToTypeID( "revealSelection" ) );
executeAction( stringIDToTypeID( "make" ), desc7, DialogModes.NO );
} else {
    var desc10 = new ActionDescriptor();
        var ref6 = new ActionReference();
        ref6.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
    desc10.putReference( stringIDToTypeID( "null" ), ref6 );
    var idmakeVisible = stringIDToTypeID( "makeVisible" );
    desc10.putBoolean( idmakeVisible, false );
executeAction( stringIDToTypeID( "select" ), desc10, DialogModes.NO );
// =======================================================
executeAction( stringIDToTypeID( "inverse" ), undefined, DialogModes.NO );
// =======================================================
    var desc18 = new ActionDescriptor();
        var ref8 = new ActionReference();
        ref8.putProperty( stringIDToTypeID( "color" ), stringIDToTypeID( "colors" ) );
    desc18.putReference( stringIDToTypeID( "null" ), ref8 );
executeAction( stringIDToTypeID( "reset" ), desc18, DialogModes.NO );
// =======================================================
    var desc5 = new ActionDescriptor();
        var ref2 = new ActionReference();
        ref2.putProperty( stringIDToTypeID( "color" ), stringIDToTypeID( "colors" ) );
    desc5.putReference( stringIDToTypeID( "null" ), ref2 );
executeAction( stringIDToTypeID( "exchange" ), desc5, DialogModes.NO );
// =======================================================
    var desc13 = new ActionDescriptor();
    desc13.putEnumerated( stringIDToTypeID( "using" ), stringIDToTypeID( "fillContents" ), stringIDToTypeID( "foregroundColor" ) );
    desc13.putUnitDouble( stringIDToTypeID( "opacity" ),stringIDToTypeID( "percentUnit" ), 100.000000 );
    desc13.putEnumerated( stringIDToTypeID( "mode" ), stringIDToTypeID( "blendMode" ), stringIDToTypeID( "normal" ) );
executeAction( stringIDToTypeID( "fill" ), desc13, DialogModes.NO );
};
// =======================================================
    var desc9 = new ActionDescriptor();
        var ref4 = new ActionReference();
        ref4.putEnumerated( idpath, idpath, idvectorMask );
        ref4.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
    desc9.putReference( idnull, ref4 );
executeAction( stringIDToTypeID( "delete" ), desc9, DialogModes.NO );
};
};
// reset;
app.preferences.rulerUnits = originalRulerUnits;
};
////////////////////////////////////
////// collect shape layers //////
function collectShapeLayers () {
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theKind = layerDesc.getInteger(stringIDToTypeID('layerKind'));
var hasLayerMask = layerDesc.hasKey(charIDToTypeID("Usrs"));
var hasStroke = layerDesc.hasKey(stringIDToTypeID("AGMStrokeStyleInfo"));
if (hasStroke == true) {hasStroke = layerDesc.getObjectValue(stringIDToTypeID("AGMStrokeStyleInfo")).getBoolean(stringIDToTypeID("strokeEnabled"))};
if (theKind == 4) {
theLayers.push([theName, theID, hasLayerMask, hasStroke])
}
};
}
catch (e) {};
};
return theLayers;
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){ 
add = undefined ? add = false:add 
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message); 
}
};

 

 

 

Votes

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 ,
Apr 06, 2024 Apr 06, 2024

Copy link to clipboard

Copied

Thank you for all this work! This one didn't work for me.

Votes

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
Community Expert ,
Apr 06, 2024 Apr 06, 2024

Copy link to clipboard

Copied

Thank you for the feedback, could you please elaborate how it did not fit your needs, it might help Christof to change/tweak his code.

Votes

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 ,
Apr 08, 2024 Apr 08, 2024

Copy link to clipboard

Copied

@PECourtejoie Thank you, yes. Nothing happens when I run it. 

 

ScreenRecording.gif

Votes

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
Community Expert ,
Apr 07, 2024 Apr 07, 2024

Copy link to clipboard

Copied

Could you please provide a file on which the Script failed? 

Votes

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 ,
Apr 08, 2024 Apr 08, 2024

Copy link to clipboard

Copied

@c.pfaffenbichler Thank you, certainly. I just made a brand new PSD with three circles.

 

Here's a link, but this is just from my Dropbox so it won't be permanent.

Votes

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
Community Expert ,
Apr 08, 2024 Apr 08, 2024

Copy link to clipboard

Copied

Thanks! 

 

The layers’ stroke settings seem to be different (though there is no stroke) from the test file I had created. 

I amended the code in the old post if you want to try it again. 

 

Votes

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 ,
Apr 09, 2024 Apr 09, 2024

Copy link to clipboard

Copied

LATEST

Wow, that's amazing! It did all of the layers at once. What a gift! Thank you for working on this. This will enable me to do more than I could before.

Votes

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
Community Expert ,
Apr 06, 2024 Apr 06, 2024

Copy link to clipboard

Copied

One more thing came to my mind: 

What about Shape Layers with a Stroke? 

edit: updated the code

Votes

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