Skip to main content
Participating Frequently
May 18, 2014
Question

For loop, selections

  • May 18, 2014
  • 1 reply
  • 340 views

I have a script I'm making that will select predefined color ranges (in my script, these are red, blue, and green), applying each of these selections to a new layer as a mask. For the most part, I have succeeded in doing this, although there are some operational situations I would like to handle better in my programming.


These are:

- The checking to see if a selection has been made, aborting the for loop if there is no selection.

- The creation of a new layer to apply so that the mask can be applied to a separate layer, not writing over what has been done to the previous layer.

I left out my attempts to implement these, as they'd muck up the clarity of this post. It's hard to explain what was going wrong, but I it had to do with the scope of the for loop, resulting in masks to write over each other on the same layer, or for an empty selection to get applied as a mask (which is undesirable).

Currently my script runs ok.. If there are red green and blue colors (exact colors) present on the layer, they will be selected and applied to masks on separate layers. If only red is present, the script will select red, create the mask on a new layer, and then error. Anyone have any ideas on handling this more efficiently? Thanks

var doc = app.activeDocument;

var fuzz = 200;

var colorRange = {};

colorRange['0r'] = '255';

colorRange['0b'] = '0';

colorRange['0g'] = '0';

colorRange['1r'] = '0';

colorRange['1b'] = '255';

colorRange['1g'] = '0';

colorRange['2r'] = '0';

colorRange['2b'] = '0';

colorRange['2g'] = '255';

for (var i = 0; i < 3; i++) {

    var layerRef = doc.artLayers.add();

    //Selects color, determined from above array.

    //When i=0 the color selected will be red.

    //When i=1 the color selected will be blue.

    //When i=2 the color selected will be green.

    var selectColour = new SolidColor();

    selectColour.rgb.red = colorRange[i + 'r'];

    selectColour.rgb.green = colorRange[i + 'b'];

    selectColour.rgb.blue = colorRange[i + 'g'];

    var scaleA = (selectColour.lab.a + 128.5) / 256;

    var desc11 = new ActionDescriptor();

    desc11.putInteger(charIDToTypeID("Fzns"), fuzz);

    var desc12 = new ActionDescriptor();

    desc12.putDouble(charIDToTypeID("Lmnc"), selectColour.lab.l);

    desc12.putDouble(charIDToTypeID("A   "), selectColour.lab.a + scaleA);

    desc12.putDouble(charIDToTypeID("B   "), selectColour.lab.b + scaleA);

    desc11.putObject(charIDToTypeID("Mnm "), charIDToTypeID("LbCl"), desc12);

    desc11.putObject(charIDToTypeID("Mxm "), charIDToTypeID("LbCl"), desc12);

    executeAction(charIDToTypeID("ClrR"), desc11, DialogModes.NO);

    //Selection is applied as a mask on the new layer.

    //If there is no selection, the script will error.

    var desc140 = new ActionDescriptor();

    desc140.putClass(charIDToTypeID('Nw  '), charIDToTypeID('Chnl'));

    var ref51 = new ActionReference();

    ref51.putEnumerated(charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Msk '));

    desc140.putReference(charIDToTypeID('At  '), ref51);

    desc140.putEnumerated(charIDToTypeID('Usng'), charIDToTypeID('UsrM'), charIDToTypeID('RvlS'));

    executeAction(charIDToTypeID('Mk  '), desc140, DialogModes.NO);

}

This topic has been closed for replies.

1 reply

c.pfaffenbichler
Community Expert
Community Expert
May 18, 2014

Does this help?

It would work with RGB and Lab images as it reselects the composite via DOM by selecting the first three Channels.

#target photoshop 

var doc = app.activeDocument; 

var fuzz = 200; 

 

 

var colorRange = {}; 

colorRange['0r'] = '255'; 

colorRange['0b'] = '0'; 

colorRange['0g'] = '0'; 

colorRange['1r'] = '0'; 

colorRange['1b'] = '255'; 

colorRange['1g'] = '0'; 

colorRange['2r'] = '0'; 

colorRange['2b'] = '0'; 

colorRange['2g'] = '255'; 

 

 

for (var i = 0; i < 3; i++) {

    //Selects color, determined from above array. 

    //When i=0 the color selected will be red. 

    //When i=1 the color selected will be blue. 

    //When i=2 the color selected will be green. 

    var selectColour = new SolidColor(); 

    selectColour.rgb.red = colorRange[i + 'r']; 

    selectColour.rgb.green = colorRange[i + 'b']; 

    selectColour.rgb.blue = colorRange[i + 'g']; 

 

 

    var scaleA = (selectColour.lab.a + 128.5) / 256; 

    var desc11 = new ActionDescriptor(); 

    desc11.putInteger(charIDToTypeID("Fzns"), fuzz); 

    var desc12 = new ActionDescriptor(); 

    desc12.putDouble(charIDToTypeID("Lmnc"), selectColour.lab.l); 

    desc12.putDouble(charIDToTypeID("A   "), selectColour.lab.a + scaleA); 

    desc12.putDouble(charIDToTypeID("B   "), selectColour.lab.b + scaleA); 

    desc11.putObject(charIDToTypeID("Mnm "), charIDToTypeID("LbCl"), desc12); 

    desc11.putObject(charIDToTypeID("Mxm "), charIDToTypeID("LbCl"), desc12); 

    executeAction(charIDToTypeID("ClrR"), desc11, DialogModes.NO); 

if (hasSelection() == true)  {

    var layerRef = doc.artLayers.add(); 

    //Selection is applied as a mask on the new layer. 

    //If there is no selection, the script will error. 

    var desc140 = new ActionDescriptor(); 

    desc140.putClass(charIDToTypeID('Nw  '), charIDToTypeID('Chnl')); 

    var ref51 = new ActionReference(); 

    ref51.putEnumerated(charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Msk ')); 

    desc140.putReference(charIDToTypeID('At  '), ref51); 

    desc140.putEnumerated(charIDToTypeID('Usng'), charIDToTypeID('UsrM'), charIDToTypeID('RvlS')); 

    executeAction(charIDToTypeID('Mk  '), desc140, DialogModes.NO);

  doc.activeChannels = [doc.channels[0], doc.channels[1], doc.channels[2]]

  };

};

////// check for seelction //////

function hasSelection(){

var ref = new ActionReference();

ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var docDesc = executeActionGet(ref);

var hasSelection = docDesc.hasKey(stringIDToTypeID("selection"));

return hasSelection;

};

SamelotAuthor
Participating Frequently
May 18, 2014

Yes, this is perfect! Thanks very much. I just briefly tested it out and it works great, I'll take an even closer look tonight.

A few things...


doc.activeChannels = [doc.channels[0], doc.channels[1], doc.channels[2]]

and

ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var docDesc = executeActionGet(ref);

var hasSelection = docDesc.hasKey(stringIDToTypeID("selection"));

Could you elaborate a bit on these two parts of the code. Is the doc.activeChannels actually making a selection? Isn't photoshop going to make a new selection anyway at the start of the loop.

c.pfaffenbichler
Community Expert
Community Expert
May 19, 2014

doc.activeChannels = [doc.channels[0], doc.channels[1], doc.channels[2]]

This selects the composite channel (the Reg, Green and Blue Channels), otherwise the Layer Mask would be the active Channel.

ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var docDesc = executeActionGet(ref);

var hasSelection = docDesc.hasKey(stringIDToTypeID("selection"));

That’s Action Manager code that determines if a Selection is active.

Unless the Color Range Selection produced an active Selection doing the rest of the operation would be useless, I guess.