About Clipping mask

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

hanyang

About Clipping mask

Post by hanyang »

If a layer is applied Clipping mask, How let JavaScript know ??

I have search "Clipping mask" in Reference Guide, but there was nothing.

Thanks.
Mike Hale

About Clipping mask

Post by Mike Hale »

I'm not sure if you want to test for a channel mask or vector mask so here are functions for both. The layer you want to test for a mask must be the active layer

Code: Select allfunction hasChannelMask() {
    var ref = new ActionReference();
   ref.putEnumerated( stringIDToTypeID( "layer" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));
   var desc= executeActionGet( ref );
    return desc.hasKey(charIDToTypeID('Usrs'));
};

function hasVectorMask(){
   var res = false;
   for(i=0;i<activeDocument.pathItems.length;i++){
      if(activeDocument.pathItems.name.match(/Vector Mask/)) res = true;
   };
   return res;
};
hanyang

About Clipping mask

Post by hanyang »

Thaks Mike Hale.

My problem is " Clipping mask", neither channel mask nor vector mask.

The "Creat Clipping mask" command below "Vector Mask" in "Layer" menu, its shortkey is Alt+Ctrl+G. You can try it and you'll understand my meaning.
Mike Hale

About Clipping mask

Post by Mike Hale »

I never noticed that Photoshop call that a clipping mask. I have always have always called it a clipping layer.

This should do the job. The layer to be tested still needs to be the active layer

Code: Select allfunction isClippingLayer(){
   var layer = activeDocument.activeLayer;
   return (layer.grouped == true && layer.kind == LayerKind.NORMAL)
};
IsraelThompson

About Clipping mask

Post by IsraelThompson »

Hey Mike,

There wouldn't, by chance, happen to be an easier way of testing to see if the selected layer IS actually the clipping layer (or bottommost layer to which a group of higher layers are all grouped), would there? Other than to check if the layer immediately above it is a clipped or grouped layer, I mean, of course.

And wouldn't your function provided, be better named, "isClippedLayer"? Or is my logic off? Also, why are you even bothering with LayerKind.NORMAL? In my experience, we have many different types of layers such as curves, hue/sat, even text, so they aren't always "normal" when we decide to merge() down, etc. Is there something in particular that I should NOT be looking for, instead of checking for NORMAL?

The reason, I'm asking all of this, is in my current particular project, I've written something that's auto merging a group if the layer exists, but I'm noticing a problem if the selected layer actually doesn't have anything grouped to it, being that it ends up merging down to the layer below it. So, in my case, I need to see if the layer in question IS the clipping layer to which any layers above it are grouped. If not, avoid the merge().

Thanks,

Izz

[quote][quote="Mike Hale"]This should do the job. The layer to be tested still needs to be the active layer
Code: Select allfunction isClippingLayer(){
   var layer = activeDocument.activeLayer;
   return (layer.grouped == true && layer.kind == LayerKind.NORMAL)
};
Paul MR

About Clipping mask

Post by Paul MR »

Would something like this work?
It tests the active layer...

Code: Select allfunction isClippingLayer(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Lyr '),charIDToTypeID('Ordn'),charIDToTypeID('Trgt') );
var desc = executeActionGet(ref);
var idx = desc.getInteger (stringIDToTypeID('itemIndex'));
var group = desc.getBoolean(stringIDToTypeID('group'));
var clipInfo=false;
if(group) clipInfo = 'topClippingLayer';
try{
    var ref = new ActionReference();
   ref.putIndex(charIDToTypeID( 'Lyr ' ), (idx + 1) );
   desc =  executeActionGet(ref);
    }catch(e){return clipInfo;}
    group = desc.getBoolean(stringIDToTypeID('group'));
    if(group && clipInfo == 'topClippingLayer' ) clipInfo = 'middleClippingLayer';
    if(group && clipInfo == false ) clipInfo = 'bottomClippingLayer';
    return clipInfo;
};

alert(isClippingLayer());
IsraelThompson

About Clipping mask

Post by IsraelThompson »

Hey Paul,

Thanks for cooking up that function! I'm still not very proficient with modifying the listener/action manager codeset, so this is a big help!

I'm noticing that "topClippingLayer" doesn't seem to ever return (as "middleClippingLayer" returns in it's place, as well as for all middle clipping layers), but "bottomClippingLayer" seems consistent which is mainly what I was looking for.

I tried tinkering around with it to see if I could get topClippingLayer working as well, but the part inside of the try{} which I'm guess was examining the layer above the selected layer (hence the idx + 1) always returned false for group if i select a middle or top clipped layer. When selected the bottommost clipping layer or even the layer below it, I noticed I got a true for group.

Thanks again!

Izz
IsraelThompson

About Clipping mask

Post by IsraelThompson »

Hey Paul,

I think I've figured out part of the problem, but can't quite explain it. Theoretically when you used "idx + 1", you would imagine you'd be specifying one index higher than the selected layer's index. The number adds up correctly. However, when you try to return the value based off of desc.getInteger(stringIDToTypeID('itemIndex')) on the new layer you're fetching data from, you interestingly get 2 numbers higher than the original idx value, not 1. The fix is to not add +1 to the idx, but my spidey sense is telling me this is only a band-aid.

I'm using CS4, btw. I'm guessing this has something to do with the background layer and Photoshop versions, and my fix might not actually be a fix to everyone, but this is a wild guess.

Izz
IsraelThompson

About Clipping mask

Post by IsraelThompson »

Anyway, my amended version of your provided code is below.

Code: Select allfunction isClippingLayer(){
    var ref = new ActionReference()
    ref.putEnumerated( charIDToTypeID('Lyr '),charIDToTypeID('Ordn'),charIDToTypeID('Trgt'))
    var desc = executeActionGet(ref)
    var idx = desc.getInteger(stringIDToTypeID('itemIndex'))
    var group = desc.getBoolean(stringIDToTypeID('group'))
    var clipInfo = false
    if ( group ) clipInfo = 'middle'
    try{
        var ref = new ActionReference()
        ref.putIndex(charIDToTypeID( 'Lyr ' ), (idx))
        desc =  executeActionGet(ref)
        group = desc.getBoolean(stringIDToTypeID('group'))
        if ( !group && clipInfo == 'middle' ) clipInfo = 'top'
    } catch (e) { return false }
    if ( group && clipInfo == false ) clipInfo = 'bottom'
    clipInfo = ( clipInfo == 'bottom' ? true : false )
    return clipInfo
}

My version removes the +1 and since I'm only looking for the bottommost clipping layer to return true, I added the below line. Otherwise, without my line, it returns either, middle, top, bottom or false, for anyone else looking to use this. Oh, also, I started with middle being the default and then switching to top, if applicable, instead of vice versa.

Code: Select allclipInfo = ( clipInfo == 'bottom' ? true : false )
Paul MR

About Clipping mask

Post by Paul MR »

I'm sorry but your amended version will fail if your document does not have a background layer, this was the mistake I made with the example, here is the corrected code...

Code: Select allfunction isClippingLayer(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Lyr '),charIDToTypeID('Ordn'),charIDToTypeID('Trgt') );
var desc = executeActionGet(ref);
var idx = desc.getInteger (stringIDToTypeID('itemIndex'));
var group = desc.getBoolean(stringIDToTypeID('group'));
var clipInfo=false;
if(group) clipInfo = 'topClippingLayer';
try{
activeDocument.backgroundLayer;
IDX = idx;
}catch(e){IDX = ++idx;}
try{
    var ref = new ActionReference();
   ref.putIndex(charIDToTypeID( 'Lyr ' ), IDX );
   desc =  executeActionGet(ref);
    }catch(e){return clipInfo;}
    group = desc.getBoolean(stringIDToTypeID('group'));
    if(group && clipInfo == 'topClippingLayer' ) clipInfo = 'middleClippingLayer';
    if(group && clipInfo == false ) clipInfo = 'bottomClippingLayer';
    return clipInfo;
};

alert(isClippingLayer());