Copy link to clipboard
Copied
I'm really, really struggling with this and I can't find any good examples for adding a stroke. Let's say I have a smart object and I want to add a stroke Layer Style to it that is only 1 pixel in size, is positioned on the inside, has 100% opacity and is solid black in color. I cannot figure out how to create a script that will add this specific layer style to the currently selected layer. (Remember, it should work for smart objects as well as regular layers.) How should I go about doing this? Can somebody please give me an example of applying a stroke layer style to a smart object layer using ExtendScript and Javascript for Photoshop?
I know this is now an old post, but figured I'd reply with an answer and a somewhat flexible script.
The only parameters I exposed in this function were size, color, opacity and position.
With the ScriptingListener plug-in you will get the ActionDescriptor code generated by Photoshop when you execute almost any action inside of PS. It's pretty easy to install, but it's not easy to read or understand, that will require a lot of testing on your end.
...Copy link to clipboard
Copied
I want to add to Stoke Multiple Layer
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hindi.
Copy link to clipboard
Copied
I want to add Layer style stoke on multiple layer Like Layer 1, Layer 2 >
Copy link to clipboard
Copied
"i want to add multiple layer on stoke" Can you explains in Photoshop steps your concept of multiple layer on a stoke?
Copy link to clipboard
Copied
at a time add stoke on Layer Like Layer 1,Layer2,Layer3 etc
Copy link to clipboard
Copied
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("targetLayers"));
r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var sel = [];
var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers"));
for (var i = 0; i < list.count; i++) sel.push(list.getReference(i).getIndex());
var d = new ActionDescriptor();
var r = new ActionReference();
r.putIndex(stringIDToTypeID("layer"), sel[0]);
d.putReference(stringIDToTypeID("null"), r);
d.putBoolean(stringIDToTypeID("makeVisible"), false);
executeAction(stringIDToTypeID("select"), d, DialogModes.NO);
var strokeColor = new RGBColor();
strokeColor.hexValue = '000000';
for (var i = 0; i < sel.length; i++) addStroke(sel[i], 10, strokeColor, 100, 'inside');
function addStroke(idx, size, color, opacity, position) {
var strokePosCharID;
switch(position) {
case 'center':
strokePosCharID = 'CtrF';
break;
case 'outside':
strokePosCharID = 'OutF';
break;
case 'inside':
strokePosCharID = 'InsF';
break;
default: break;
}
var desc = new ActionDescriptor();
var ref190 = new ActionReference();
ref190.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( "Lefx" ) );
//ref190.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
ref190.putIndex( charIDToTypeID( "Lyr " ), idx);
desc.putReference( charIDToTypeID( "null" ), ref190 );
var fxDesc = new ActionDescriptor();
var fxPropDesc = new ActionDescriptor();
fxPropDesc.putBoolean( charIDToTypeID( "enab" ), true );
fxPropDesc.putBoolean( stringIDToTypeID( "present" ), true );
fxPropDesc.putBoolean( stringIDToTypeID( "showInDialog" ), true );
fxPropDesc.putEnumerated( charIDToTypeID( "Styl" ), charIDToTypeID( "FStl" ), charIDToTypeID( strokePosCharID ) );
fxPropDesc.putEnumerated( charIDToTypeID( "PntT" ), charIDToTypeID( "FrFl" ), charIDToTypeID( "SClr" ) );
fxPropDesc.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Nrml" ) );
fxPropDesc.putUnitDouble( charIDToTypeID( "Opct" ), charIDToTypeID( "#Prc" ), opacity );
fxPropDesc.putUnitDouble( charIDToTypeID( "Sz " ), charIDToTypeID( "#Pxl") , size );
var colorDesc = new ActionDescriptor();
colorDesc.putDouble( charIDToTypeID( "Rd " ), color.red);
colorDesc.putDouble( charIDToTypeID( "Grn " ), color.green );
colorDesc.putDouble( charIDToTypeID( "Bl " ), color.blue );
fxPropDesc.putObject( charIDToTypeID( "Clr " ), charIDToTypeID( "RGBC" ), colorDesc );
fxPropDesc.putBoolean( stringIDToTypeID( "overprint" ), false );
fxDesc.putObject( charIDToTypeID( "FrFX" ), charIDToTypeID( "FrFX" ), fxPropDesc );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Lefx" ), fxDesc );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}
ЗЫ. халявы больше не будет (для вас точно).
Copy link to clipboard
Copied
Thanku so much @r-bin
Next time i will clear
Copy link to clipboard
Copied
The code posted here in this thread I through it into a script I had to process targeted layer target the layers you want to stroked then run the script. Look into the script you may learn some things about layers. Here is a couple of screen captures targeted layers Script ran.
#target photoshop
app.bringToFront();
// ensure at least one document open
if (!documents.length) alert('There are no documents open.', 'No Document');
else {
// declare Global variables
var layersInfo = "";
//main(); // at least one document exists proceed
app.activeDocument.suspendHistory('ProcessSelectedLayers','main()');
}
// MAIN
function main() {
var orig_ruler_units = app.preferences.rulerUnits; // Save Ruler Units
var orig_type_units = app.preferences.typeUnits; // Save Type Units
var orig_display_dialogs = app.displayDialogs; // Save Dialog Display
app.preferences.rulerUnits = Units.PIXELS; // Set the ruler units to PIXELS
app.preferences.typeUnits = TypeUnits.POINTS; // Set Type units to POINTS
app.displayDialogs = DialogModes.NO; // Set Dialogs off
var doc = app.activeDocument; // Active Document
var SelectedLayersIdx = getSelectedLayersIndex(doc);// get selected layers ID
try {
for (var i = 0; i < SelectedLayersIdx.length; i++) {
selectLayerByIndex(SelectedLayersIdx[i]);
processLayer(doc.activeLayer); // process layer
}
if (layersInfo != "") alert(layersInfo); // Spit it out
}
// display error message if something goes wrong
catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }
setSelectedLayersIdx(SelectedLayersIdx); // Restore selected layers
app.displayDialogs = orig_display_dialogs; // Restore display dialogs
app.preferences.typeUnits = orig_type_units; // Restore ruler units to original settings
app.preferences.rulerUnits = orig_ruler_units; // Restore units to original settings
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
function processLayer(layer) {
/*
* Add Stroke Effect
* @Param {Number} size : 1 - 250
* @Param {Object} color : RGBColor object
* @Param {Number} opacity : 0 - 100
* @Param {Number} position : center / outside / inside
*/
// Set color as HEX
var strokeColor = new RGBColor();
strokeColor.hexValue = '000000';
addStroke(5, strokeColor, 100, 'inside');
//alert(layerInfo(layer));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
function layerInfo(layer) {
try {
if (layer.kind==LayerKind.TEXT) {
// Display some TextItem data
var txtInfo = "";
txtInfo = txtInfo + "\nLayerTextItemContents='" + layer.textItem.contents + "'";
txtInfo = txtInfo + "\nLayerTextItemFont='" + layer.textItem.font + "'";
txtInfo = txtInfo + "\nLayerTextItemSize='" + layer.textItem.size + "'";
txtInfo = txtInfo + "\nLayerTextItemColor'" + layer.textItem.color.rgb.red + "," + layer.textItem.color.rgb.green + "," + layer.textItem.color.rgb.blue + "'";
txtInfo = txtInfo + "\nLayerTextItemDirection='" + layer.textItem.direction + "'";
txtInfo = txtInfo + "\nLayerTextItemAntiAliasMethod='" + layer.textItem.antiAliasMethod + "'";
txtInfo = txtInfo + "\nLayerTextItemPosition='" +layer.textItem.position + "'";
txtInfo = txtInfo + "\nLayerTextItemKind='" + layer.textItem.kind + "'";
if (layer.textItem.kind==TextType.PARAGRAPHTEXT) {
txtInfo = txtInfo + "\nLayerTextItemWidth='" + layer.textItem.width + "'";
txtInfo = txtInfo + "\nLayerTextItemHeight='" + layer.textItem.height + "'";
txtInfo = txtInfo + "\nLayerTextItemTextComposer ='" + layer.textItem.textComposer + "'";
}
}
else {txtInfo="";}
}
catch(e) {
txtInfo= txtInfo + "\ntextItem " + e + ': on line ' + e.line
layer.textItem.contents = layer.textItem.contents;
layerInfo(layer);
}
// alert(txtInfo);
/*
alert("typename='" + layer.typename + "'"
+ "\nvisible='" + layer.visible + "'"
+ "\nlayerName='" + layer.name + "'"
+ "\nisBackgroundLayer = " + layer.isBackgroundLayer
+ "\nlayerID='" + layer.id + "'"
+ "\nitemIndex='" + layer.itemIndex + "'"
+ "\nlayerKind='" + layer.kind + "'"
+ "\nallLocked='" + layer.allLocked + "'"
+ "\npixelsLocked = " + layer.pixelsLocked
+ "\npositionLocked = " + layer.positionLocked
+ "\ntransparentPixelsLocked = " + layer.transparentPixelsLocked
+ "\nblendMode='" + layer.blendMode + "'"
+ "\nopacity='" + layer.opacity + "'"
+ "\nfillOpacity = " + layer.fillOpacity
+ "\nbounds='" + layer.bounds + "'"
+ "\nboundsNoEffects='" + layer.boundsNoEffects + "'"
+ "\nlinkedLayers='" + layer.linkedLayers + "'"
+ "\nparent='" + layer.parent + "'"
+ "\ngrouped = " + layer.grouped
+ "\nlayerMaskDensity = " + layer.layerMaskDensity
+ "\nlayerMaskFeather = " + layer.layerMaskFeather
+ "\nvectorMaskDensity = " + layer.vectorMaskDensity
+ "\nvectorMaskFeather = " + layer.vectorMaskFeather
+ "\nxmpMetadata='" + obj_to_str(layer.xmpMetadata) + "'"
);
*/
layerInfo = "typename='" + layer.typename + "'"
+ "\nvisible='" + layer.visible + "'"
+ "\nlayerName='" + layer.name + "'"
+ "\nisBackgroundLayer = " + layer.isBackgroundLayer
+ "\nlayerID='" + layer.id + "'"
+ "\nitemIndex='" + layer.itemIndex + "'"
+ "\nlayerKind='" + layer.kind + "'"
+ "\nallLocked='" + layer.allLocked + "'"
+ "\npixelsLocked = " + layer.pixelsLocked
+ "\npositionLocked = " + layer.positionLocked
+ "\ntransparentPixelsLocked = " + layer.transparentPixelsLocked
+ "\nblendMode='" + layer.blendMode + "'"
+ "\nopacity='" + layer.opacity + "'"
+ "\nfillOpacity = " + layer.fillOpacity
+ "\nbounds='" + layer.bounds + "'"
+ "\nboundsNoEffects='" + layer.boundsNoEffects + "'"
+ "\nlinkedLayers='" + layer.linkedLayers + "'"
+ "\nparent='" + layer.parent + "'"
+ "\ngrouped = " + layer.grouped
+ "\nlayerMaskDensity = " + layer.layerMaskDensity
+ "\nlayerMaskFeather = " + layer.layerMaskFeather
+ "\nvectorMaskDensity = " + layer.vectorMaskDensity
+ "\nvectorMaskFeather = " + layer.vectorMaskFeather
+ "\nxmpMetadata='" + obj_to_str(layer.xmpMetadata) + "'"
+ txtInfo ;
return layerInfo;
// there is also additional artlayer info
}
//Thanks to r-bin
function obj_to_str(obj){var str = ""; for (var p in obj) if(obj.hasOwnProperty(p))try{str+=p+"::"+obj[p]+"\n";}catch(e){};return str;}
/*
TextItem Properties * indicates in the not always available
//txtInfo = txtInfo + "\nLayerTextItemLanguage='" + layer.textItem.language + "'"
//txtInfo = txtInfo + "\nLayerTextItemFauxBold='" + layer.textItem.fauxBold + "'"
//txtInfo = txtInfo + "\nLayerTextItemFauxItalic='" + layer.textItem.fauxItalic + "'"
//txtInfo = txtInfo + "\nLayerTextItemUnderline='" + layer.textItem.underline + "'"
//txtInfo = txtInfo + "\nLayerTextItemCapitalization='" + layer.textItem.capitalization + "'"
*antiAliasMethod
autoKerning
autoLeadingAmount
baselineShift
capitalization
*color
*contents
desiredGlyphScaling
desiredLetterScaling
desiredWordScaling
*direction
fauxBold
fauxItalic
firstLineIndent
*font
hangingPunctuation
*height
hyphenateAfterFirst
hyphenateBeforeLast
hyphenateCapitalWords
hyphenateWordsLongerThan
hyphenation
hyphenationZone
hyphenLimit
justification
*kind
language
leading
leftIndent
ligatures
maximumGlyphScaling
maximumLetterScaling
maximumWordScaling
minimumGlyphScaling
minimumLetterScaling
minimumWordScaling
noBreak
oldStyle
*parent
*position
rightIndent
*size
spaceAfter
spaceBefore
strikeThru
*textComposer
tracking
typename
underline
useAutoLeading
verticalScale
warpBend
warpDirection
warpHorizontalDistortion
warpStyle
warpVerticalDistortion
*width
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
function cTID(s) {return app.charIDToTypeID(s);}
function sTID(s) {return app.stringIDToTypeID(s);}
// SELECT LAYER MASK
function Select_Layermask(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('Chnl'), cTID('Chnl'), cTID('Msk '));
desc1.putReference(cTID('null'), ref1);
desc1.putBoolean(cTID('MkVs'), false);
executeAction(cTID('slct'), desc1, dialogMode);
};
///////////////////////////////////////////////////////////////////////////////
// Function: hasLayerMask
// Usage: see if there is a raster layer mask
// Input: <none> Must have an open document
// Return: true if there is a vector mask
///////////////////////////////////////////////////////////////////////////////
function hasLayerMask() {
var hasLayerMask = false;
try {
var ref = new ActionReference();
var keyUserMaskEnabled = app.charIDToTypeID( 'UsrM' );
ref.putProperty( app.charIDToTypeID( 'Prpr' ), keyUserMaskEnabled );
ref.putEnumerated( app.charIDToTypeID( 'Lyr ' ), app.charIDToTypeID( 'Ordn' ), app.charIDToTypeID( 'Trgt' ) );
var desc = executeActionGet( ref );
if ( desc.hasKey( keyUserMaskEnabled ) ) { hasLayerMask = true; }
}
catch(e) { hasLayerMask = false; }
return hasLayerMask;
}
// GET SELECTED LAYERS
function getSelectedLayers() {
var resultLayers=new Array();
try {
var descGrp = new ActionDescriptor();
var refGrp = new ActionReference();
refGrp.putEnumerated(cTID( "Lyr " ),cTID( "Ordn" ),cTID( "Trgt" ));
descGrp.putReference(cTID( "null" ), refGrp );
executeAction( sTID( "groupLayersEvent" ), descGrp, DialogModes.NO );
for (var ix=0;ix<app.activeDocument.activeLayer.layers.length;ix++){resultLayers.push(app.activeDocument.activeLayer.layers[ix])}
var desc5 = new ActionDescriptor();
var ref2 = new ActionReference();
ref2.putEnumerated( cTID( "HstS" ), cTID( "Ordn" ), cTID( "Prvs" ) );
desc5.putReference( cTID( "null" ), ref2 );
executeAction( cTID( "slct" ), desc5, DialogModes.NO );
}
catch (err) { }
return resultLayers;
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetSelectedLayers Index
// Input: Document
// Return: array selectedLayers indexes
///////////////////////////////////////////////////////////////////////////////
function getSelectedLayersIndex(doc) {
var selectedLayers = [];
var ref = new ActionReference();
ref.putEnumerated(cTID('Dcmn'), cTID('Ordn'), cTID('Trgt'));
var desc = executeActionGet(ref);
if (desc.hasKey(sTID('targetLayers'))) {
desc = desc.getList(sTID('targetLayers'));
var c = desc.count;
for (var i = 0; i < c; i++) {
try {
doc.backgroundLayer;
selectedLayers.push(desc.getReference(i).getIndex());
}
catch (e) { selectedLayers.push(desc.getReference(i).getIndex() + 1); }
}
} else {
var ref = new ActionReference();
ref.putProperty(cTID('Prpr'), cTID('ItmI'));
ref.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
try {
doc.backgroundLayer;
selectedLayers.push(executeActionGet(ref).getInteger(cTID('ItmI')) - 1);
}
catch (e) { selectedLayers.push(executeActionGet(ref).getInteger(cTID('ItmI'))); }
}
return selectedLayers;
}
///////////////////////////////////////////////////////////////////////////////
// Function: setSelectedLayers
// Usage: Selects Layers
// Input: Array selectedLayers index
// Return: <none>
///////////////////////////////////////////////////////////////////////////////
function setSelectedLayersIdx( layerIndexes ) {
selectLayerByIndex( layerIndexes[0] ); // first select the first one
for ( var i = 1; i < layerIndexes.length; i++) { // then add to the selection
selectLayerByIndex( layerIndexes[i], true );
}
}
function selectLayerByIndex(index, add) {
var ref = new ActionReference();
ref.putIndex(charIDToTypeID("Lyr "), index);
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) {}
}
///////////////////////////////////////////////////////////////////////////////
// Function: setSelectedLayers
// Usage: Selects Layers
// Input: Array selectedLayers
// Return: <none>
///////////////////////////////////////////////////////////////////////////////
function setSelectedLayers( layerIndexesOrNames ) {
setSelectedLayer( layerIndexesOrNames[0] ); // first select the first one
for ( var i = 1; i < layerIndexesOrNames.length; i++) { // then add to the selection
addSelectedLayer( layerIndexesOrNames[i] );
}
}
// Add Stroke to layer
// Javier Aroche
function addStroke(size, color, opacity, position) {
var strokePosCharID;
switch(position) {
case 'center':
strokePosCharID = 'CtrF';
break;
case 'outside':
strokePosCharID = 'OutF';
break;
case 'inside':
strokePosCharID = 'InsF';
break;
default: break;
}
var desc = new ActionDescriptor();
var ref190 = new ActionReference();
ref190.putProperty( charIDToTypeID( "Prpr" ), charIDToTypeID( "Lefx" ) );
ref190.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc.putReference( charIDToTypeID( "null" ), ref190 );
var fxDesc = new ActionDescriptor();
var fxPropDesc = new ActionDescriptor();
fxPropDesc.putBoolean( charIDToTypeID( "enab" ), true );
fxPropDesc.putBoolean( stringIDToTypeID( "present" ), true );
fxPropDesc.putBoolean( stringIDToTypeID( "showInDialog" ), true );
fxPropDesc.putEnumerated( charIDToTypeID( "Styl" ), charIDToTypeID( "FStl" ), charIDToTypeID( strokePosCharID ) );
fxPropDesc.putEnumerated( charIDToTypeID( "PntT" ), charIDToTypeID( "FrFl" ), charIDToTypeID( "SClr" ) );
fxPropDesc.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Nrml" ) );
fxPropDesc.putUnitDouble( charIDToTypeID( "Opct" ), charIDToTypeID( "#Prc" ), opacity );
fxPropDesc.putUnitDouble( charIDToTypeID( "Sz " ), charIDToTypeID( "#Pxl") , size );
var colorDesc = new ActionDescriptor();
colorDesc.putDouble( charIDToTypeID( "Rd " ), color.red);
colorDesc.putDouble( charIDToTypeID( "Grn " ), color.green );
colorDesc.putDouble( charIDToTypeID( "Bl " ), color.blue );
fxPropDesc.putObject( charIDToTypeID( "Clr " ), charIDToTypeID( "RGBC" ), colorDesc );
fxPropDesc.putBoolean( stringIDToTypeID( "overprint" ), false );
fxDesc.putObject( charIDToTypeID( "FrFX" ), charIDToTypeID( "FrFX" ), fxPropDesc );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Lefx" ), fxDesc );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}
Copy link to clipboard
Copied
Thanku so much @JJMack also Very Well and fine worked it
Copy link to clipboard
Copied
You posted third time the same code, and again with bugs I mentioned the code can not work with. You did it also without </> that makes these bugs happen. It's not needed on one page to have 4 times exactly same quite long code as it makes threads unreadable. This is spamming and I warned you of not doing it, also in this topic. If you will keep such poor behaviour that threads look as garbage your posts will be marked as spam. It's enough to link the codes you talk about. The same is about repeating same question again and again, like you're doing now and did earlier. You said something once and it's enough. Either someone will help you or not.
Anyway I noticed you don't take seriuosly anything said like the above, so probably you won't stop spamming. Be ready shortly you may cross limit of someone's patience 😉
Copy link to clipboard
Copied
I must say, not having the ability to edit/correct posts makes it really hard to keep this forum clean..
To stay on-topic.. All examples I find for applying layer style effects seem to override any effect already applied. So it a layer has an outerglow, when adding a stroke, the outerglow is gone.
Is there any way to really ADD layer effects without clearing the previous effects?
Copy link to clipboard
Copied
Ask the moderator to edit your posts, until you reach some amount of them to do it yourself.