Copy link to clipboard
Copied
Hi, I've been trying to automate a task, but got stuck hard on an issue (couple of hours of various retries without success).
What I'm trying to do: convert selected layer to a shape.
Workflow: select layer, ctrl select it (to highlight), "Make work path from selection", convert to shape (pen tool, shape button).
I can get everything to work except the last step (convert path to shape). I've tried to include and exclude select pen tool, didn't do anything.
When I run my script, it creates the path, creates a shape layer, but it has no color. Looking through the raw code, I've noticed one "magic number", and after testing a little, I've figured out it's a max layer id + 1 (so I guess new layer id?).
I've also tried to remove this number (and the `putInteger`), didn't help either.
When I run the script without the last step, and manually click on the shape button, it works, and produces the exact same raw code.
At this point, I can't pin-point anything that could be causing the issue.
The raw code to convert path to shape is below. In this case, the magic number is 102 (right at the bottom). I didn't notify it whatsoever yet.
var idMk = charIDToTypeID( "Mk " );
var desc257 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref17 = new ActionReference();
var idcontentLayer = stringIDToTypeID( "contentLayer" );
ref17.putClass( idcontentLayer );
desc257.putReference( idnull, ref17 );
var idUsng = charIDToTypeID( "Usng" );
var desc258 = new ActionDescriptor();
var idType = charIDToTypeID( "Type" );
var desc259 = new ActionDescriptor();
var idClr = charIDToTypeID( "Clr " );
var desc260 = new ActionDescriptor();
var idRd = charIDToTypeID( "Rd " );
desc260.putDouble( idRd, 0.000000 );
var idGrn = charIDToTypeID( "Grn " );
desc260.putDouble( idGrn, 0.000000 );
var idBl = charIDToTypeID( "Bl " );
desc260.putDouble( idBl, 0.000000 );
var idRGBC = charIDToTypeID( "RGBC" );
desc259.putObject( idClr, idRGBC, desc260 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc258.putObject( idType, idsolidColorLayer, desc259 );
var idShp = charIDToTypeID( "Shp " );
var desc261 = new ActionDescriptor();
var idTrgp = charIDToTypeID( "Trgp" );
var idPthK = charIDToTypeID( "PthK" );
var idTrgp = charIDToTypeID( "Trgp" );
desc261.putEnumerated( idTrgp, idPthK, idTrgp );
var idpathClass = stringIDToTypeID( "pathClass" );
desc258.putObject( idShp, idpathClass, desc261 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
var desc262 = new ActionDescriptor();
var idstrokeStyleVersion = stringIDToTypeID( "strokeStyleVersion" );
desc262.putInteger( idstrokeStyleVersion, 2 );
var idstrokeEnabled = stringIDToTypeID( "strokeEnabled" );
desc262.putBoolean( idstrokeEnabled, false );
var idfillEnabled = stringIDToTypeID( "fillEnabled" );
desc262.putBoolean( idfillEnabled, true );
var idstrokeStyleLineWidth = stringIDToTypeID( "strokeStyleLineWidth" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idstrokeStyleLineWidth, idPxl, 1.000000 );
var idstrokeStyleLineDashOffset = stringIDToTypeID( "strokeStyleLineDashOffset" );
var idPnt = charIDToTypeID( "#Pnt" );
desc262.putUnitDouble( idstrokeStyleLineDashOffset, idPnt, 0.000000 );
var idstrokeStyleMiterLimit = stringIDToTypeID( "strokeStyleMiterLimit" );
desc262.putDouble( idstrokeStyleMiterLimit, 100.000000 );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
var idstrokeStyleButtCap = stringIDToTypeID( "strokeStyleButtCap" );
desc262.putEnumerated( idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
var idstrokeStyleMiterJoin = stringIDToTypeID( "strokeStyleMiterJoin" );
desc262.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleAlignInside = stringIDToTypeID( "strokeStyleAlignInside" );
desc262.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignInside );
var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
desc262.putBoolean( idstrokeStyleScaleLock, false );
var idstrokeStyleStrokeAdjust = stringIDToTypeID( "strokeStyleStrokeAdjust" );
desc262.putBoolean( idstrokeStyleStrokeAdjust, false );
var idstrokeStyleLineDashSet = stringIDToTypeID( "strokeStyleLineDashSet" );
var list15 = new ActionList();
desc262.putList( idstrokeStyleLineDashSet, list15 );
var idstrokeStyleBlendMode = stringIDToTypeID( "strokeStyleBlendMode" );
var idBlnM = charIDToTypeID( "BlnM" );
var idNrml = charIDToTypeID( "Nrml" );
desc262.putEnumerated( idstrokeStyleBlendMode, idBlnM, idNrml );
var idstrokeStyleOpacity = stringIDToTypeID( "strokeStyleOpacity" );
var idPrc = charIDToTypeID( "#Prc" );
desc262.putUnitDouble( idstrokeStyleOpacity, idPrc, 100.000000 );
var idstrokeStyleContent = stringIDToTypeID( "strokeStyleContent" );
var desc263 = new ActionDescriptor();
var idClr = charIDToTypeID( "Clr " );
var desc264 = new ActionDescriptor();
var idRd = charIDToTypeID( "Rd " );
desc264.putDouble( idRd, 0.000000 );
var idGrn = charIDToTypeID( "Grn " );
desc264.putDouble( idGrn, 0.000000 );
var idBl = charIDToTypeID( "Bl " );
desc264.putDouble( idBl, 0.000000 );
var idRGBC = charIDToTypeID( "RGBC" );
desc263.putObject( idClr, idRGBC, desc264 );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
desc262.putObject( idstrokeStyleContent, idsolidColorLayer, desc263 );
var idstrokeStyleResolution = stringIDToTypeID( "strokeStyleResolution" );
desc262.putDouble( idstrokeStyleResolution, 72.000000 );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
desc258.putObject( idstrokeStyle, idstrokeStyle, desc262 );
var idcontentLayer = stringIDToTypeID( "contentLayer" );
desc257.putObject( idUsng, idcontentLayer, desc258 );
var idLyrI = charIDToTypeID( "LyrI" );
desc257.putInteger( idLyrI, 102 );
executeAction( idMk, desc257, DialogModes.NO );
Here is my action, test it https://drive.google.com/file/d/1XNb3ZbzO8Tj4IYCr2ssfLs9ADG0cLHxt/view?usp=sharing
You must have selected layer with pixels and transparency on that layer like paint with brush on blank transparent layer then run action.
@Samuel_PFD – As you were originally trying to get code to work, here is a version of the action from @Bojan Živković converted into an action via xbytor's xtools:
#target photoshop
//
// Shapefromlayer.jsx
//
//
// Generated Thu Apr 28 2022 19:55:17 GMT+1000
//
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
//
//==================== Shape from layer ==============
//
function Shapefromlayer() {
// Set
function step1(enabled
...
Copy link to clipboard
Copied
[Edit]
I'm running psd 2021 v22.5.1
Copy link to clipboard
Copied
What do you mean when you say "but it has no color"?
Your script creates a shape with black color for me.
The color is set at the beginning of your code, namely:
var idMk = charIDToTypeID( "Mk " );
var desc257 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref17 = new ActionReference();
var idcontentLayer = stringIDToTypeID( "contentLayer" );
ref17.putClass( idcontentLayer );
desc257.putReference( idnull, ref17 );
var idUsng = charIDToTypeID( "Usng" );
var desc258 = new ActionDescriptor();
var idType = charIDToTypeID( "Type" );
var desc259 = new ActionDescriptor();
var idClr = charIDToTypeID( "Clr " );
var desc260 = new ActionDescriptor();
var idRd = charIDToTypeID( "Rd " );
desc260.putDouble( idRd, 0.000000 ); // R here
var idGrn = charIDToTypeID( "Grn " );
desc260.putDouble( idGrn, 0.000000 ); // G here
var idBl = charIDToTypeID( "Bl " );
desc260.putDouble( idBl, 0.000000 ); // B here
var idRGBC = charIDToTypeID( "RGBC" );
desc259.putObject( idClr, idRGBC, desc260 );
......
Lines of code
var idLyrI = charIDToTypeID( "LyrI" );
desc257.putInteger( idLyrI, 102 );
are rubbish in the new photoshops. Doesn't affect anything, you can throw it away.
P.S. tested on CS6
Copy link to clipboard
Copied
That's exactly what it's supposed to do.
What I've done and still gotten the issue:
create new psd file, add a layer, draw a line with a brush, select the layer, run script (I'll include it below).
When I use the script without the last `convert_to_shape`, and do it manually (click shape button on top), it converts the path to a black shape.
When I keep the `convert_to_shape` uncommented, and run it, it creates an empty shape layer, with nothing there.
Script (not cleaned up or beautified yet):
var layer_id = get_selected_layer_id();
layer_special_select();
convert_to_path();
select_pen();
// convert_to_shape(get_max_layer_id() + 1);
// layer_select(layer_id)
// layer_delete();
function get_selected_layer_id() {
var ref = new ActionReference();
ref.putProperty(s2t("property"), s2t("layerID"));
ref.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var desc = executeActionGet(ref);
var targetLayerID = getDescValue(desc, s2t('layerID'));
return targetLayerID;
}
function layer_special_select() {
var idsetd = charIDToTypeID("setd");
var desc966 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref180 = new ActionReference();
var idChnl = charIDToTypeID("Chnl");
var idfsel = charIDToTypeID("fsel");
ref180.putProperty(idChnl, idfsel);
desc966.putReference(idnull, ref180);
var idT = charIDToTypeID("T ");
var ref181 = new ActionReference();
var idChnl = charIDToTypeID("Chnl");
var idChnl = charIDToTypeID("Chnl");
var idTrsp = charIDToTypeID("Trsp");
ref181.putEnumerated(idChnl, idChnl, idTrsp);
desc966.putReference(idT, ref181);
executeAction(idsetd, desc966, DialogModes.NO);
}
function convert_to_path() {
var idMk = charIDToTypeID("Mk ");
var desc968 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref182 = new ActionReference();
var idPath = charIDToTypeID("Path");
ref182.putClass(idPath);
desc968.putReference(idnull, ref182);
var idFrom = charIDToTypeID("From");
var ref183 = new ActionReference();
var idcsel = charIDToTypeID("csel");
var idfsel = charIDToTypeID("fsel");
ref183.putProperty(idcsel, idfsel);
desc968.putReference(idFrom, ref183);
var idTlrn = charIDToTypeID("Tlrn");
var idPxl = charIDToTypeID("#Pxl");
desc968.putUnitDouble(idTlrn, idPxl, 0.500000);
executeAction(idMk, desc968, DialogModes.NO);
}
function select_pen() {
var idslct = charIDToTypeID( "slct" );
var desc255 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref16 = new ActionReference();
var idpenTool = stringIDToTypeID( "penTool" );
ref16.putClass( idpenTool );
desc255.putReference( idnull, ref16 );
var iddontRecord = stringIDToTypeID( "dontRecord" );
desc255.putBoolean( iddontRecord, true );
var idforceNotify = stringIDToTypeID( "forceNotify" );
desc255.putBoolean( idforceNotify, true );
executeAction( idslct, desc255, DialogModes.NO );
}
function convert_to_shape(layer_id) {
var idMk = s2t("make");
var desc971 = new ActionDescriptor();
var idnull = s2t("null");
var ref185 = new ActionReference();
var idcontentLayer = s2t("contentLayer");
ref185.putClass(idcontentLayer);
desc971.putReference(idnull, ref185);
var idUsng = s2t("using");
var desc972 = new ActionDescriptor();
var idType = s2t("type");
var desc973 = new ActionDescriptor();
var idClr = s2t("color");
var desc974 = new ActionDescriptor();
var idRd = s2t("red");
desc974.putDouble(idRd, 0);
var idGrn = s2t("grain");
desc974.putDouble(idGrn, 0);
var idBl = s2t("blue");
desc974.putDouble(idBl, 0);
var idRGBC = s2t("RGBColor");
desc973.putObject(idClr, idRGBC, desc974);
var idsolidColorLayer = s2t("solidColorLayer");
desc972.putObject(idType, idsolidColorLayer, desc973);
var idShp = s2t("shape");
var desc975 = new ActionDescriptor();
var idTrgp = s2t("targetPathIndex");
var idPthK = s2t("pathKind");
desc975.putEnumerated(idTrgp, idPthK, idTrgp);
var idpathClass = s2t("pathClass");
desc972.putObject(idShp, idpathClass, desc975);
var idstrokeStyle = s2t("strokeStyle");
var desc976 = new ActionDescriptor();
var idstrokeStyleVersion = s2t("strokeStyleVersion");
desc976.putInteger(idstrokeStyleVersion, 2);
var idstrokeEnabled = s2t("strokeEnabled");
desc976.putBoolean(idstrokeEnabled, false);
var idfillEnabled = s2t("fillEnabled");
desc976.putBoolean(idfillEnabled, true);
var idstrokeStyleLineWidth = s2t("strokeStyleLineWidth");
var idPxl = s2t("pixelsUnit");
desc976.putUnitDouble(idstrokeStyleLineWidth, idPxl, 1.000000);
var idstrokeStyleLineDashOffset = s2t("strokeStyleLineDashOffset");
var idPnt = s2t("pointsUnit");
desc976.putUnitDouble(idstrokeStyleLineDashOffset, idPnt, 0.000000);
var idstrokeStyleMiterLimit = s2t("strokeStyleMiterLimit");
desc976.putDouble(idstrokeStyleMiterLimit, 100.000000);
var idstrokeStyleLineCapType = s2t("strokeStyleLineCapType");
var idstrokeStyleLineCapType = s2t("strokeStyleLineCapType");
var idstrokeStyleButtCap = s2t("strokeStyleButtCap");
desc976.putEnumerated(idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap);
var idstrokeStyleLineJoinType = s2t("strokeStyleLineJoinType");
var idstrokeStyleLineJoinType = s2t("strokeStyleLineJoinType");
var idstrokeStyleMiterJoin = s2t("strokeStyleMiterJoin");
desc976.putEnumerated(idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin);
var idstrokeStyleLineAlignment = s2t("strokeStyleLineAlignment");
var idstrokeStyleLineAlignment = s2t("strokeStyleLineAlignment");
var idstrokeStyleAlignInside = s2t("strokeStyleAlignInside");
desc976.putEnumerated(idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignInside);
var idstrokeStyleScaleLock = s2t("strokeStyleScaleLock");
desc976.putBoolean(idstrokeStyleScaleLock, false);
var idstrokeStyleStrokeAdjust = s2t("strokeStyleStrokeAdjust");
desc976.putBoolean(idstrokeStyleStrokeAdjust, false);
var idstrokeStyleLineDashSet = s2t("strokeStyleLineDashSet");
var list94 = new ActionList();
desc976.putList(idstrokeStyleLineDashSet, list94);
var idstrokeStyleBlendMode = s2t("strokeStyleBlendMode");
var idBlnM = s2t("blendMode");
var idNrml = s2t("normal");
desc976.putEnumerated(idstrokeStyleBlendMode, idBlnM, idNrml);
var idstrokeStyleOpacity = s2t("strokeStyleOpacity");
var idPrc = s2t("percentUnit");
desc976.putUnitDouble(idstrokeStyleOpacity, idPrc, 100.000000);
var idstrokeStyleContent = s2t("strokeStyleContent");
var desc977 = new ActionDescriptor();
var idClr = s2t("color");
var desc978 = new ActionDescriptor();
var idRd = s2t("red");
desc978.putDouble(idRd, 0.000000);
var idGrn = s2t("grain");
desc978.putDouble(idGrn, 0.000000);
var idBl = s2t("blue");
desc978.putDouble(idBl, 0.000000);
var idRGBC = s2t("RGBColor");
desc977.putObject(idClr, idRGBC, desc978);
var idsolidColorLayer = s2t("solidColorLayer");
desc976.putObject(idstrokeStyleContent, idsolidColorLayer, desc977);
var idstrokeStyleResolution = s2t("strokeStyleResolution");
desc976.putDouble(idstrokeStyleResolution, 72.000000);
var idstrokeStyle = s2t("strokeStyle");
desc972.putObject(idstrokeStyle, idstrokeStyle, desc976);
var idcontentLayer = s2t("contentLayer");
desc971.putObject(idUsng, idcontentLayer, desc972);
var idLyrI = s2t("layerID");
desc971.putInteger(idLyrI, layer_id);
executeAction(idMk, desc971, DialogModes.NO);
}
function layer_select(layer_id) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIdentifier(s2t("layer"), layer_id);
desc.putReference(s2t("null"), ref);
executeAction(s2t("select"), desc, DialogModes.NO);
}
function layer_delete() {
var idDlt = charIDToTypeID( "Dlt " );
var desc360 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref25 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref25.putEnumerated( idLyr, idOrdn, idTrgt );
desc360.putReference( idnull, ref25 );
executeAction( idDlt, desc360, DialogModes.NO );
}
function get_max_layer_id() {
var max_id = 0;
var start = getObjectProperty('document', 'hasBackgroundLayer') ? 0 : 1;
var end = getObjectProperty('document', 'numberOfLayers');
for (var i = start; i <= end; i++) {
var idLyr = getLayerProperty(i, 'layerID');
if (idLyr > max_id) {
max_id = idLyr;
}
}
return max_id;
}
function getLayerProperty(index, property) {
ref = new ActionReference();
ref.putProperty(s2t('property'), s2t(property))
ref.putIndex(s2t('layer'), index);
var desc = executeActionGet(ref);
return getDescValue(desc, s2t(property));
}
function getObjectProperty(obj, property) {
var ref = new ActionReference();
ref.putProperty(s2t('property'), s2t(property));
ref.putEnumerated(s2t(obj), s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(ref), s2t(property));
}
function s2t(s) {
return stringIDToTypeID(s);
}
function t2s(t) {
return typeIDToStringID(t);
}
function getDescValue(descriptor, property) {
switch(descriptor.getType(property)) {
case DescValueType.OBJECTTYPE: return { type: t2s(descriptor.getObjectType(property)), value: descriptor.getObjectValue(property) };
case DescValueType.LISTTYPE: return descriptor.getList(property);
case DescValueType.REFERENCETYPE: return descriptor.getReference(property);
case DescValueType.BOOLEANTYPE: return descriptor.getBoolean(property);
case DescValueType.STRINGTYPE: return descriptor.getString(property);
case DescValueType.INTEGERTYPE: return descriptor.getInteger(property);
case DescValueType.LARGEINTEGERTYPE: return descriptor.getLargeInteger(property);
case DescValueType.DOUBLETYPE: return descriptor.getDouble(property);
case DescValueType.ALIASTYPE: return descriptor.getPath(property);
case DescValueType.CLASSTYPE: return descriptor.getClass(property);
case DescValueType.UNITDOUBLE: return (descriptor.getUnitDoubleValue(property));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(descriptor.getEnumerationType(property)), value: t2s(descriptor.getEnumerationValue(property)) };
default: return 0;
};
}
Copy link to clipboard
Copied
>>>>When I keep the `convert_to_shape` uncommented, and run it, it creates an empty shape layer, with nothing there.
Maybe I didn't understand something. Record your step to convert the work path to a shape in an Action. Check the operation of the recorded Action. If as a result you get an empty shape, then this is a bug in your version of Photoshop. Write a bug report. ActionManager code, this is the code that is executed in the recorded Action. If it doesn't work in an Action, then it won't work in a script with this code either.
Copy link to clipboard
Copied
doesn't work:
added a line, selected it, used the script (with `convert_to_shape` commented out), pressed record, clicked shape button, stopped recording (this worked fine, because I presesed the button).
Added a new line, removed everything else, selected it, used the same script (so it again only creates the path), clicked run action, and it did the same thing (empty shape).
I've checked the action, so it doesn't have any weird name associations, and nothing is present. It indeed might be a bug in photoshop, which sucks.
Thanks for the help though.
Copy link to clipboard
Copied
What is supposed script to do? What is requirement to run script (layer selected, path in the Paths panel etc...).
Copy link to clipboard
Copied
just replied to another one with how to reproduce, and what it should do (with images).
And yes, you need to have path selected in the pen menu (or so I was told).
Copy link to clipboard
Copied
Per your instructions, running 22.5.7 version of Ps. I have selected layer with stroke drawn on it (with transparency around stroke). Script is creating empty path and shape layer without anything on it, so to speak empty shape layer.
Copy link to clipboard
Copied
Yes, that's the issue I'm facing.
But if I do the last step manually, it converts it properly to a shape, but the script itself can't execute the `convert_to_shape` properly.
Copy link to clipboard
Copied
I am able to record action with following steps:
With the rest I can not help. Version of Ps is 22.5.7.
To what you see above add Select path >pathname< before deleting it.
Copy link to clipboard
Copied
Did you try to use the action on other layers again?
I've followed your steps EXACTLY one-to-one, and it doesn't work for me. Even tried to update to v22.5.7 for any bug-fixes.
Copy link to clipboard
Copied
Here is my action, test it https://drive.google.com/file/d/1XNb3ZbzO8Tj4IYCr2ssfLs9ADG0cLHxt/view?usp=sharing
You must have selected layer with pixels and transparency on that layer like paint with brush on blank transparent layer then run action.
Copy link to clipboard
Copied
It works, no clue what you've done differently, but it works!
So thank you.
Copy link to clipboard
Copied
@Samuel_PFD – As you were originally trying to get code to work, here is a version of the action from @Bojan Živković converted into an action via xbytor's xtools:
#target photoshop
//
// Shapefromlayer.jsx
//
//
// Generated Thu Apr 28 2022 19:55:17 GMT+1000
//
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
//
//==================== Shape from layer ==============
//
function Shapefromlayer() {
// Set
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Trsp'));
desc1.putReference(cTID('T '), ref2);
executeAction(cTID('setd'), desc1, dialogMode);
};
// Make
function step2(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Path'));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putProperty(cTID('csel'), sTID("selection"));
desc1.putReference(cTID('From'), ref2);
desc1.putUnitDouble(cTID('Tlrn'), cTID('#Pxl'), 0.5);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Make
function step3(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Path'));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putProperty(cTID('Path'), cTID('WrPt'));
desc1.putReference(cTID('From'), ref2);
desc1.putString(cTID('Nm '), "Path 1");
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Make
function step4(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Lyr '));
desc1.putReference(cTID('null'), ref1);
desc1.putInteger(cTID('LyrI'), 7);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Select
function step5(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putName(cTID('Path'), "Path 1");
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
};
// Make
function step6(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(sTID("contentLayer"));
desc1.putReference(cTID('null'), ref1);
var desc2 = new ActionDescriptor();
var desc3 = new ActionDescriptor();
var desc4 = new ActionDescriptor();
desc4.putDouble(cTID('Rd '), 11.7081711441278);
desc4.putDouble(cTID('Grn '), 46.9727640599012);
desc4.putDouble(cTID('Bl '), 198.992221355438);
desc3.putObject(cTID('Clr '), sTID("RGBColor"), desc4);
desc2.putObject(cTID('Type'), sTID("solidColorLayer"), desc3);
desc1.putObject(cTID('Usng'), sTID("contentLayer"), desc2);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Select
function step7(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putName(cTID('Path'), "Path 1");
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
};
// Delete
function step8(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Path'), cTID('Ordn'), cTID('Trgt'));
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('Dlt '), desc1, dialogMode);
};
step1(); // Set
step2(); // Make
step3(); // Make
step4(); // Make
step5(); // Select
step6(); // Make
step7(); // Select
step8(); // Delete
};
//=========================================
// Shapefromlayer.main
//=========================================
//
Shapefromlayer.main = function () {
Shapefromlayer();
};
Shapefromlayer.main();
// EOF
"Shapefromlayer.jsx"
// EOF
Copy link to clipboard
Copied
Amazing, I was thinking of doing the same thing (but with more work). Are these the tools you are referring to? http://ps-scripts.sourceforge.net/xtools.html
I'll adapt your code with mine, to remove the first layer, and set color from foreground color, but this is perfect.
I'll mark it as correct when I try it out too!
Copy link to clipboard
Copied
Apologies, I should have posted the link as the one that you found is old:
EDIT - Here is 2.3, I incorrectly posted 2.2 before:
https://sourceforge.net/projects/ps-scripts/files/xtools/v2.3/
Copy link to clipboard
Copied
I think the issue (or part of the issue), why it didn't work for me was, that I set the shortcut as Ctrl + Alt + Shift + Z.
So it probably interfered with undo, or something like that.
I've also noticed, that "foregroundColor" sometimes returns a CMYK object instead of HSV? What's up with that.
Anyway, here's my full script (with some extra functions that are not used). I'm using it to select, vectorize (with foreground color) and remove original layer:
#target photoshop
//
// Shapefromlayer.jsx
//
//
// Generated Thu Apr 28 2022 19:55:17 GMT+1000
// https://community.adobe.com/t5/photoshop-ecosystem-discussions/action-manager-convert-path-to-shape/m-p/12909949#M640017
//
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
//
//==================== Shape from layer ==============
//
function Shapefromlayer() {
// Set
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Trsp'));
desc1.putReference(cTID('T '), ref2);
executeAction(cTID('setd'), desc1, dialogMode);
};
// Make
function step2(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Path'));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putProperty(cTID('csel'), sTID("selection"));
desc1.putReference(cTID('From'), ref2);
desc1.putUnitDouble(cTID('Tlrn'), cTID('#Pxl'), 0.5);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Make
function step3(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Path'));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putProperty(cTID('Path'), cTID('WrPt'));
desc1.putReference(cTID('From'), ref2);
desc1.putString(cTID('Nm '), "Path 1");
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Make
function step4(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(cTID('Lyr '));
desc1.putReference(cTID('null'), ref1);
desc1.putInteger(cTID('LyrI'), 7);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Select
function step5(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putName(cTID('Path'), "Path 1");
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
};
// Make
function step6(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putClass(sTID("contentLayer"));
desc1.putReference(cTID('null'), ref1);
var desc2 = new ActionDescriptor();
var desc3 = new ActionDescriptor();
var desc4 = new ActionDescriptor();
desc4.putDouble(cTID('Rd '), rgb[0]);
desc4.putDouble(cTID('Grn '), rgb[1]);
desc4.putDouble(cTID('Bl '), rgb[2]);
desc3.putObject(cTID('Clr '), sTID("RGBColor"), desc4);
desc2.putObject(cTID('Type'), sTID("solidColorLayer"), desc3);
desc1.putObject(cTID('Usng'), sTID("contentLayer"), desc2);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Select
function step7(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putName(cTID('Path'), "Path 1");
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
};
// Delete
function step8(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Path'), cTID('Ordn'), cTID('Trgt'));
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('Dlt '), desc1, dialogMode);
};
step1(); // Set
step2(); // Make
step3(); // Make
step4(); // Make
step5(); // Select
step6(); // Make
step7(); // Select
step8(); // Delete
};
// https://stackoverflow.com/a/17243070/13000953
function HSVtoRGB(h, s, v) {
var r, g, b, i, f, p, q, t;
if (arguments.length === 1) {
s = h.s, v = h.v, h = h.h;
}
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
var layer_id = get_selected_layer_id();
var fc = get_foreground_color();
var rgb = HSVtoRGB(fc[0] / 360, fc[1] / 100, fc[2] / 100);
Shapefromlayer(rgb[0], rgb[1], rgb[2]);
layer_select(layer_id)
layer_delete();
function get_foreground_color() {
r = new ActionReference();
r.putProperty(s2t("property"), s2t("foregroundColor"));
r.putEnumerated(stringIDToTypeID("application"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
d = executeActionGet(r);
prop = getDescValue(d, s2t("foregroundColor")).value;
hue = getDescValue(prop, s2t("hue"));
saturation = getDescValue(prop, s2t("saturation"));
brightness = getDescValue(prop, s2t("brightness"));
return [hue, saturation, brightness];
}
function get_selected_layer_id() {
var ref = new ActionReference();
ref.putProperty(s2t("property"), s2t("layerID"));
ref.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var desc = executeActionGet(ref);
var targetLayerID = getDescValue(desc, s2t('layerID'));
return targetLayerID;
}
function layer_special_select() {
var idsetd = charIDToTypeID("setd");
var desc966 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref180 = new ActionReference();
var idChnl = charIDToTypeID("Chnl");
var idfsel = charIDToTypeID("fsel");
ref180.putProperty(idChnl, idfsel);
desc966.putReference(idnull, ref180);
var idT = charIDToTypeID("T ");
var ref181 = new ActionReference();
var idChnl = charIDToTypeID("Chnl");
var idChnl = charIDToTypeID("Chnl");
var idTrsp = charIDToTypeID("Trsp");
ref181.putEnumerated(idChnl, idChnl, idTrsp);
desc966.putReference(idT, ref181);
executeAction(idsetd, desc966, DialogModes.NO);
}
function convert_to_path() {
var idMk = charIDToTypeID("Mk ");
var desc968 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref182 = new ActionReference();
var idPath = charIDToTypeID("Path");
ref182.putClass(idPath);
desc968.putReference(idnull, ref182);
var idFrom = charIDToTypeID("From");
var ref183 = new ActionReference();
var idcsel = charIDToTypeID("csel");
var idfsel = charIDToTypeID("fsel");
ref183.putProperty(idcsel, idfsel);
desc968.putReference(idFrom, ref183);
var idTlrn = charIDToTypeID("Tlrn");
var idPxl = charIDToTypeID("#Pxl");
desc968.putUnitDouble(idTlrn, idPxl, 0.500000);
executeAction(idMk, desc968, DialogModes.NO);
}
function select_pen() {
var idslct = charIDToTypeID( "slct" );
var desc255 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref16 = new ActionReference();
var idpenTool = stringIDToTypeID( "penTool" );
ref16.putClass( idpenTool );
desc255.putReference( idnull, ref16 );
var iddontRecord = stringIDToTypeID( "dontRecord" );
desc255.putBoolean( iddontRecord, true );
var idforceNotify = stringIDToTypeID( "forceNotify" );
desc255.putBoolean( idforceNotify, true );
executeAction( idslct, desc255, DialogModes.NO );
}
function convert_to_shape(layer_id) {
var idMk = s2t("make");
var desc971 = new ActionDescriptor();
var idnull = s2t("null");
var ref185 = new ActionReference();
var idcontentLayer = s2t("contentLayer");
ref185.putClass(idcontentLayer);
desc971.putReference(idnull, ref185);
var idUsng = s2t("using");
var desc972 = new ActionDescriptor();
var idType = s2t("type");
var desc973 = new ActionDescriptor();
var idClr = s2t("color");
var desc974 = new ActionDescriptor();
var idRd = s2t("red");
desc974.putDouble(idRd, 0);
var idGrn = s2t("grain");
desc974.putDouble(idGrn, 0);
var idBl = s2t("blue");
desc974.putDouble(idBl, 0);
var idRGBC = s2t("RGBColor");
desc973.putObject(idClr, idRGBC, desc974);
var idsolidColorLayer = s2t("solidColorLayer");
desc972.putObject(idType, idsolidColorLayer, desc973);
var idShp = s2t("shape");
var desc975 = new ActionDescriptor();
var idTrgp = s2t("targetPathIndex");
var idPthK = s2t("pathKind");
desc975.putEnumerated(idTrgp, idPthK, idTrgp);
var idpathClass = s2t("pathClass");
desc972.putObject(idShp, idpathClass, desc975);
var idstrokeStyle = s2t("strokeStyle");
var desc976 = new ActionDescriptor();
var idstrokeStyleVersion = s2t("strokeStyleVersion");
desc976.putInteger(idstrokeStyleVersion, 2);
var idstrokeEnabled = s2t("strokeEnabled");
desc976.putBoolean(idstrokeEnabled, false);
var idfillEnabled = s2t("fillEnabled");
desc976.putBoolean(idfillEnabled, true);
var idstrokeStyleLineWidth = s2t("strokeStyleLineWidth");
var idPxl = s2t("pixelsUnit");
desc976.putUnitDouble(idstrokeStyleLineWidth, idPxl, 1.000000);
var idstrokeStyleLineDashOffset = s2t("strokeStyleLineDashOffset");
var idPnt = s2t("pointsUnit");
desc976.putUnitDouble(idstrokeStyleLineDashOffset, idPnt, 0.000000);
var idstrokeStyleMiterLimit = s2t("strokeStyleMiterLimit");
desc976.putDouble(idstrokeStyleMiterLimit, 100.000000);
var idstrokeStyleLineCapType = s2t("strokeStyleLineCapType");
var idstrokeStyleLineCapType = s2t("strokeStyleLineCapType");
var idstrokeStyleButtCap = s2t("strokeStyleButtCap");
desc976.putEnumerated(idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap);
var idstrokeStyleLineJoinType = s2t("strokeStyleLineJoinType");
var idstrokeStyleLineJoinType = s2t("strokeStyleLineJoinType");
var idstrokeStyleMiterJoin = s2t("strokeStyleMiterJoin");
desc976.putEnumerated(idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin);
var idstrokeStyleLineAlignment = s2t("strokeStyleLineAlignment");
var idstrokeStyleLineAlignment = s2t("strokeStyleLineAlignment");
var idstrokeStyleAlignInside = s2t("strokeStyleAlignInside");
desc976.putEnumerated(idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignInside);
var idstrokeStyleScaleLock = s2t("strokeStyleScaleLock");
desc976.putBoolean(idstrokeStyleScaleLock, false);
var idstrokeStyleStrokeAdjust = s2t("strokeStyleStrokeAdjust");
desc976.putBoolean(idstrokeStyleStrokeAdjust, false);
var idstrokeStyleLineDashSet = s2t("strokeStyleLineDashSet");
var list94 = new ActionList();
desc976.putList(idstrokeStyleLineDashSet, list94);
var idstrokeStyleBlendMode = s2t("strokeStyleBlendMode");
var idBlnM = s2t("blendMode");
var idNrml = s2t("normal");
desc976.putEnumerated(idstrokeStyleBlendMode, idBlnM, idNrml);
var idstrokeStyleOpacity = s2t("strokeStyleOpacity");
var idPrc = s2t("percentUnit");
desc976.putUnitDouble(idstrokeStyleOpacity, idPrc, 100.000000);
var idstrokeStyleContent = s2t("strokeStyleContent");
var desc977 = new ActionDescriptor();
var idClr = s2t("color");
var desc978 = new ActionDescriptor();
var idRd = s2t("red");
desc978.putDouble(idRd, 0.000000);
var idGrn = s2t("grain");
desc978.putDouble(idGrn, 0.000000);
var idBl = s2t("blue");
desc978.putDouble(idBl, 0.000000);
var idRGBC = s2t("RGBColor");
desc977.putObject(idClr, idRGBC, desc978);
var idsolidColorLayer = s2t("solidColorLayer");
desc976.putObject(idstrokeStyleContent, idsolidColorLayer, desc977);
var idstrokeStyleResolution = s2t("strokeStyleResolution");
desc976.putDouble(idstrokeStyleResolution, 72.000000);
var idstrokeStyle = s2t("strokeStyle");
desc972.putObject(idstrokeStyle, idstrokeStyle, desc976);
var idcontentLayer = s2t("contentLayer");
desc971.putObject(idUsng, idcontentLayer, desc972);
var idLyrI = s2t("layerID");
desc971.putInteger(idLyrI, layer_id);
executeAction(idMk, desc971, DialogModes.NO);
}
function layer_select(layer_id) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIdentifier(s2t("layer"), layer_id);
desc.putReference(s2t("null"), ref);
executeAction(s2t("select"), desc, DialogModes.NO);
}
function layer_delete() {
var idDlt = charIDToTypeID( "Dlt " );
var desc360 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref25 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref25.putEnumerated( idLyr, idOrdn, idTrgt );
desc360.putReference( idnull, ref25 );
executeAction( idDlt, desc360, DialogModes.NO );
}
function get_max_layer_id() {
var max_id = 0;
var start = getObjectProperty('document', 'hasBackgroundLayer') ? 0 : 1;
var end = getObjectProperty('document', 'numberOfLayers');
for (var i = start; i <= end; i++) {
var idLyr = getLayerProperty(i, 'layerID');
if (idLyr > max_id) {
max_id = idLyr;
}
}
return max_id;
}
function getLayerProperty(index, property) {
ref = new ActionReference();
ref.putProperty(s2t('property'), s2t(property))
ref.putIndex(s2t('layer'), index);
var desc = executeActionGet(ref);
return getDescValue(desc, s2t(property));
}
function getObjectProperty(obj, property) {
var ref = new ActionReference();
ref.putProperty(s2t('property'), s2t(property));
ref.putEnumerated(s2t(obj), s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(ref), s2t(property));
}
function s2t(s) {
return stringIDToTypeID(s);
}
function t2s(t) {
return typeIDToStringID(t);
}
function getDescValue(descriptor, property) {
switch(descriptor.getType(property)) {
case DescValueType.OBJECTTYPE: return { type: t2s(descriptor.getObjectType(property)), value: descriptor.getObjectValue(property) };
case DescValueType.LISTTYPE: return descriptor.getList(property);
case DescValueType.REFERENCETYPE: return descriptor.getReference(property);
case DescValueType.BOOLEANTYPE: return descriptor.getBoolean(property);
case DescValueType.STRINGTYPE: return descriptor.getString(property);
case DescValueType.INTEGERTYPE: return descriptor.getInteger(property);
case DescValueType.LARGEINTEGERTYPE: return descriptor.getLargeInteger(property);
case DescValueType.DOUBLETYPE: return descriptor.getDouble(property);
case DescValueType.ALIASTYPE: return descriptor.getPath(property);
case DescValueType.CLASSTYPE: return descriptor.getClass(property);
case DescValueType.UNITDOUBLE: return (descriptor.getUnitDoubleValue(property));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(descriptor.getEnumerationType(property)), value: t2s(descriptor.getEnumerationValue(property)) };
default: return 0;
};
}
Copy link to clipboard
Copied
I have a question. Why are you always creating an empty layer? What is this for?
: )
Copy link to clipboard
Copied
To ensure nothing will mess because when you have empty layer + path selected + fill layer then you will get shape layer. It is habit, and probably secure option. I got there somehow through testing and experimentation in the past (I guess).