In my code I often create new layer ( using Stdlib.createSolidFillLayer for example) then set its name and opacity through properties:
Code: Select allvar l = Stdlib.createSolidFillLayer();
l.name = 'foo'
l.opacity = 69;
When there is many (>10) layer, this operations tend to be slow. So I've extended createSolidFillLayer in order to speed up things a bit:
Code: Select allStdlib.layerColorsEnum = {none: 'None', red: 'Rd ', orange: 'Orng', yellow: 'Ylw ', green: 'Grn ', blue: 'Bl ', violet: 'Vlt ', gray: 'Gry '};
Stdlib.blendModesEnum = {passThrough: 'passThrough', normal: 'normal', dissolve: 'dissolve', darken: 'darken', multipl: 'multipl', colorBurn: 'colorBurn', linearBurn: 'linearBurn', darkerColor: 'darkerColor', lighten: 'lighten', screen: 'screen', colorDodge: 'colorDodge', linearDodge: 'linearDodge', lighterColor: 'lighterColor', overlay: 'overlay', softLight: 'softLight', hardLight: 'hardLight', vividLight: 'vividLight', linearLight: 'linearLight', pinLight: 'pinLight', hardMix: 'hardMix', difference: 'difference', exclusion: 'exclusion', hue: 'hue', saturation: 'saturation', color: 'color', luminosity: 'luminosity'};
/*
* Creates a solid fill layer using low-level functions
* [in*] name: String -- layer name, def: auto PS name
* [in*] opacity: Integer from range [0,100] -- layer opacity, def: 100
* [in*] color: enum Stdlib.layerColorsEnum -- color of layer (on layers panel), def: Stdlib.layerColorsEnum.none
* [in*] blandMode: enum Stdlib.blendModesEnum -- blending mode of the layer, def: Stdlib.blendModesEnum.normal
* Returns void
* Remark: It is faster than standard API at least in CS4.
* Remark: Do not pass an argument or pass undefined to get default value
* Example: Stdlib.createLayerGroup('my group', 50, Stdlib.layerColorsEnum.red, Stdlib.blendModesEnum.passThrough);
*/
Stdlib.createSolidFillLayer = function(doc, color, name, opacity, layerColor, blendMode, clipToPrevious) {
// in original createSolidFillLayer author forgot to add 'doc' argument
// add it w/o braking compatibility
if(doc instanceof SolidColor) {
color=doc; doc=app.activeDocument};
if (!color) {
color = Stdlib.createRGBColor(0, 0, 0);
}
function _ftn() {
var desc = new ActionDescriptor();
var clref = new ActionReference();
clref.putClass(sTID('contentLayer'));
desc.putReference(cTID('null'), clref);
var tdesc = new ActionDescriptor();
if (name) {
tdesc.putString( cTID( "Nm " ), name );
}
if (opacity) {
tdesc.putUnitDouble( cTID( "Opct" ), cTID( "#Prc" ), opacity );
}
if (layerColor) {
tdesc.putEnumerated( cTID( "Clr " ), cTID( "Clr " ), cTID( layerColor ) );
}
if (blendMode) {
tdesc.putEnumerated( cTID( "Md " ), cTID( "BlnM" ), cTID( blendMode ) );
}
if (clipToPrevious) {
tdesc.putBoolean( cTID( "Grup" ), !!clipToPrevious );
}
var scldesc = new ActionDescriptor();
var rgbdesc = new ActionDescriptor();
rgbdesc.putDouble(cTID('Rd '), color.rgb.red);
rgbdesc.putDouble(cTID('Grn '), color.rgb.green);
rgbdesc.putDouble(cTID('Bl '), color.rgb.blue);
scldesc.putObject(cTID('Clr '), cTID('RGBC'), rgbdesc);
tdesc.putObject(cTID('Type'), sTID('solidColorLayer'), scldesc);
desc.putObject(cTID('Usng'), sTID('contentLayer'), tdesc);
executeAction(cTID('Mk '), desc, DialogModes.NO);
}
Stdlib.wrapLC(doc, _ftn);
return doc.activeLayer;
};
It can be used to replace original function or just-another-lib-function after adding 'Ex' suffix to its name. Some tests
Code: Select all// (7258418+7289173+7138296+10416049+10483223+10368110)/6=8825545
// Remark: number of layers DO affect efficiency
doc = activeDocument;
function testCaseAPI() {
for (var i=1; i<=10; ++i) {
var g = Stdlib.createSolidFillLayer(doc, Stdlib.createRGBColor(0,255,0));
g.name = "Fill " + i;
g.opacity = 10*i;
}
}
// (5114606+4017009+4198933+3083992+3119524+2943980)/6=3746340
// Remark: number of layers do NOT affect efficiency
// Conclusion: 57,55% faster than AIP version
function testCaseStdlib() {
for (var i=1; i<=10; ++i) {
Stdlib.createSolidFillLayer_new(doc, Stdlib.createRGBColor(255,0,0), "Fill " + i,10*i);
var g = doc.activeLayer;
}
}
// first 3 tests
/*
testCaseAPI();
testCaseAPI();
testCaseAPI();
testCaseStdlib();
testCaseStdlib();
testCaseStdlib(); //*/
// next 3 tests
//*
testCaseStdlib();
testCaseStdlib();
testCaseStdlib();
testCaseAPI();
testCaseAPI();
testCaseAPI(); //*/
It would be nice to add 'create layer mask' argument, but I have no idea how to create layer with layer mask (not simply adding it to created layer).
createSolidFillLayer Extended
createSolidFillLayer Extended
SzopeN wrote:It would be nice to add 'create layer mask' argument, but I have no idea how to create layer with layer mask (not simply adding it to created layer).
If you have an active selection or path when you call the Action Manager function it will create a channel or vector mask when the solidfill layer is created.
Or you could use a function similar to the on below to add a channel mask to an existing layer
createLayerMask = function(){
var desc = new ActionDescriptor();
desc.putClass( charIDToTypeID( "Nw " ), charIDToTypeID( "Chnl" ) );
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( "Msk " ) );
desc.putReference( charIDToTypeID( "At " ), ref );
desc.putEnumerated( charIDToTypeID( "Usng" ), charIDToTypeID( "UsrM" ), charIDToTypeID( "RvlA" ) );
executeAction( charIDToTypeID( "Mk " ), desc, DialogModes.NO );
};
If you have an active selection or path when you call the Action Manager function it will create a channel or vector mask when the solidfill layer is created.
Or you could use a function similar to the on below to add a channel mask to an existing layer
createLayerMask = function(){
var desc = new ActionDescriptor();
desc.putClass( charIDToTypeID( "Nw " ), charIDToTypeID( "Chnl" ) );
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( "Msk " ) );
desc.putReference( charIDToTypeID( "At " ), ref );
desc.putEnumerated( charIDToTypeID( "Usng" ), charIDToTypeID( "UsrM" ), charIDToTypeID( "RvlA" ) );
executeAction( charIDToTypeID( "Mk " ), desc, DialogModes.NO );
};
createSolidFillLayer Extended
Yes, that part I've figured out already. But the problem remains: how to CREATE layer with (or w/o) layer mask using additional entries in ActionDescriptor. Naturally I can make a full-canvas selection before creating fill layer, but it is (at least) one operation more. On the other hand, when 'use default masks on fill layers' is enabled, deleting mask after layer creation is the only way I know for creating bare fill layer.
In other words the problems are:
How (and whether it is possible) to:
create fill layer w/ user mask ('use default masks on fill layers' disabled) create fill layer w/o user mask ('use default masks on fill layers' enabled) create fill layer w/ or w/o mask regardless selection (hide/reveal all) create fill layer with mask mode 'hide selection'
using only one call to executeAction. Of course, there are simple solution of this problems using 'create and then do sth.' method. I'm pretty sure, there is no one-step way of doing that, but I'm still searching...
In other words the problems are:
How (and whether it is possible) to:
create fill layer w/ user mask ('use default masks on fill layers' disabled) create fill layer w/o user mask ('use default masks on fill layers' enabled) create fill layer w/ or w/o mask regardless selection (hide/reveal all) create fill layer with mask mode 'hide selection'
using only one call to executeAction. Of course, there are simple solution of this problems using 'create and then do sth.' method. I'm pretty sure, there is no one-step way of doing that, but I'm still searching...
createSolidFillLayer Extended
SzopeN wrote:I'm pretty sure, there is no one-step way of doing that, but I'm still searching...
I don't think there is a one-step way either. Unlike the layer properties that you added to the layer creation above adding a mask would require making a channel or path. I don't see how that could be done with one executeAction.
The channel or path is not part of the layer's descriptor so I don't think that you could even add an existing channel or path.
I don't think there is a one-step way either. Unlike the layer properties that you added to the layer creation above adding a mask would require making a channel or path. I don't see how that could be done with one executeAction.
The channel or path is not part of the layer's descriptor so I don't think that you could even add an existing channel or path.