• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

How to get bounding box of a layer mask?

New Here ,
Mar 28, 2019 Mar 28, 2019

Copy link to clipboard

Copied

I am trying to get the bounding box of a layer mask, as well as a group containing layer masks... yet no matter what I do, it always returns the full size of the canvas 0,0 to max.  Is there a way to do this via javascript?  I would think Photoshop is smart enough to spit this back, considering I can scale a layer mask and the mask portion is scaled, not the entire canvas size.

TOPICS
Actions and scripting

Views

2.9K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

People's Champ , Mar 29, 2019 Mar 29, 2019

sz20044 

I appreciate the help.  Sorry guys, I am not an avid Photoshop or Javascript expert here in scripting.

I have tried your selection script and it errors out if I fill in the mask channel name.  I have also tried just RGB and I get the same error:

Error: Illegal Argument

Tried:

selection_from_channel("RGB");

//selection_from_channel("Msk ");

and

selection_from_channel("HL Mask");      <--- Name of the Layer Mask Channel

//selection_from_channel("Msk ");

This is not a channel name, but a four-chara
...

Votes

Translate

Translate
Adobe
People's Champ ,
Mar 28, 2019 Mar 28, 2019

Copy link to clipboard

Copied

1. Convert Mask channel to selection

2. Use selection.bounds

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 28, 2019 Mar 28, 2019

Copy link to clipboard

Copied

Is there a site for scripting commands for photoshop you can refer me to?  I have no clue how to issue a javascript command on how to convert a selected layer's mask to selection.

I am assuming using the bounds would be something like:

var height = activeDocument.activeLayer.bounds[2]-activeDocument.activeLayer.bounds[0];

var width = activeDocument.activeLayer.bounds[3]-activeDocument.activeLayer.bounds[1];

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 28, 2019 Mar 28, 2019

Copy link to clipboard

Copied

It seems that  a layer mask  and a layers bounds are the same somwtimes.  When the layer actual content  smaller then then layers mask selection boynds. The layers bounds  is the layer pixels bounds.

Capture.jpg

// enable double-clicking from Mac Finder or Windows Explorer

#target photoshop // this command only works in Photoshop CS2 and higher

// bring application forward for double-click events

app.bringToFront();

// Save the current preferences

var startRulerUnits = app.preferences.rulerUnits;

// Set Photoshop to use pixels

app.preferences.rulerUnits = Units.PIXELS;

try{

var LB = activeDocument.activeLayer.bounds;

var LWidth = (LB[2].value) - (LB[0].value);

var LHeight = (LB[3].value) - (LB[1].value);

MarkX((LB[0].value + LWidth/2));

MarkX(LB[0].value);

MarkX(LB[2].value);

MarkY((LB[1].value + LHeight/2));

MarkY(LB[1].value)

MarkY(LB[3].value)

alert("'" + activeDocument.activeLayer.name + "' Layer Bounds\nTop Left " +  LB[0].value + "X," +  LB[1].value + "Y   Bottom Right "  +  LB[2].value + "X," +  LB[3].value

+ "Y\nWidth " +  LWidth + "px   Height " + LHeight +"px"

+ "\nLayer center relative to canvas " + (LB[0].value + LWidth/2) + "X," +  (LB[1].value + LHeight/2) +"Y"

);

}

catch(e){alert("Requires a layer targered");}

// Return the app preferences

app.preferences.rulerUnits = startRulerUnits;

function MarkX(x) {

// =======================================================

var idMk = charIDToTypeID( "Mk  " );

    var desc61 = new ActionDescriptor();

    var idNw = charIDToTypeID( "Nw  " );

        var desc62 = new ActionDescriptor();

        var idPstn = charIDToTypeID( "Pstn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc62.putUnitDouble( idPstn, idPxl, x);

        var idOrnt = charIDToTypeID( "Ornt" );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idVrtc = charIDToTypeID( "Vrtc" );

        desc62.putEnumerated( idOrnt, idOrnt, idVrtc );

    var idGd = charIDToTypeID( "Gd  " );

    desc61.putObject( idNw, idGd, desc62 );

executeAction( idMk, desc61, DialogModes.NO );

}

function MarkY(y) {

// =======================================================

var idMk = charIDToTypeID( "Mk  " );

    var desc63 = new ActionDescriptor();

    var idNw = charIDToTypeID( "Nw  " );

        var desc64 = new ActionDescriptor();

        var idPstn = charIDToTypeID( "Pstn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc64.putUnitDouble( idPstn, idPxl, y );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idHrzn = charIDToTypeID( "Hrzn" );

        desc64.putEnumerated( idOrnt, idOrnt, idHrzn );

    var idGd = charIDToTypeID( "Gd  " );

    desc63.putObject( idNw, idGd, desc64 );

executeAction( idMk, desc63, DialogModes.NO );

}

Here is a script to fit  a layer to the current selection the is a selection bounds you can use. Also add a layer mask  to shape the layer to the selection.  Slection Bounds was broken in CS2 I had to use other means back than.

var startRulerUnits = app.preferences.rulerUnits;   

app.preferences.rulerUnits = Units.PIXELS;  

 

if (app.activeDocument.activeLayer.kind == LayerKind.NORMAL  || app.activeDocument.activeLayer.kind == LayerKind.SMARTOBJECT && hasLayerMask()) { deleteLayerMask ();}

 

var LB = activeDocument.selection.bounds; 

var width = LB[2]-LB[0]; 

var height = LB[3]-LB[1]; 

var IB = activeDocument.activeLayer.bounds; 

var dwidth = IB[2]-IB[0]; 

var dheight = IB[3]-IB[1]; 

var ratio = height/width;  

var dratio = dheight/dwidth;  

if (dratio>ratio) {                           // layer's Aspect Ratio less the Canvas area Aspect Ratio

var percentageChange = ((width/dwidth)*100);  // Resize to canvas area width

app.activeDocument.activeLayer.resize(percentageChange,percentageChange,AnchorPosition.MIDDLECENTER);

}

else {

var percentageChange = ((height/dheight)*100); // resize to canvas area height

app.activeDocument.activeLayer.resize(percentageChange,percentageChange,AnchorPosition.MIDDLECENTER);

}

align('AdCH'); // align to horizontal centers

align('AdCV'); // align to vertical centers

addLayermask(); // add layer mask to mask off excess

app.preferences.rulerUnits = startRulerUnits;           // restore ruler units

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Helper Functions

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function align(method) {

var desc = new ActionDescriptor();

var ref = new ActionReference();

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

desc.putReference( charIDToTypeID( "null" ), ref );

desc.putEnumerated( charIDToTypeID( "Usng" ), charIDToTypeID( "ADSt" ), charIDToTypeID( method ) );

try{executeAction( charIDToTypeID( "Algn" ), desc, DialogModes.NO );}

catch(e){}

}

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;  

}

function deleteLayerMask (apply) {

// Delet Layer mask default to not apply first

if (apply == undefined) {var apply = false};

try {

var idDlt = charIDToTypeID( "Dlt " );

    var desc9 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref5 = new ActionReference();

        var idChnl = charIDToTypeID( "Chnl" );

        var idChnl = charIDToTypeID( "Chnl" );

        var idMsk = charIDToTypeID( "Msk " );

        ref5.putEnumerated( idChnl, idChnl, idMsk );

    desc9.putReference( idnull, ref5 );

    var idAply = charIDToTypeID( "Aply" );

    desc9.putBoolean( idAply, apply );

executeAction( idDlt, desc9, DialogModes.NO );

}

catch (e) {}

};

function addLayermask(){

// Add layer Mask

var idMk = charIDToTypeID( "Mk  " );

    var desc52 = new ActionDescriptor();

    var idNw = charIDToTypeID( "Nw  " );

    var idChnl = charIDToTypeID( "Chnl" );

    desc52.putClass( idNw, idChnl );

    var idAt = charIDToTypeID( "At  " );

        var ref19 = new ActionReference();

        var idChnl = charIDToTypeID( "Chnl" );

        var idChnl = charIDToTypeID( "Chnl" );

        var idMsk = charIDToTypeID( "Msk " );

        ref19.putEnumerated( idChnl, idChnl, idMsk );

    desc52.putReference( idAt, ref19 );

    var idUsng = charIDToTypeID( "Usng" );

    var idUsrM = charIDToTypeID( "UsrM" );

    var idRvlS = charIDToTypeID( "RvlS" );

    desc52.putEnumerated( idUsng, idUsrM, idRvlS );

executeAction( idMk, desc52, DialogModes.NO );

// Un link layer mask just added fron the layers content

var idsetd = charIDToTypeID( "setd" );

    var desc2 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref1 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref1.putEnumerated( idLyr, idOrdn, idTrgt );

    desc2.putReference( idnull, ref1 );

    var idT = charIDToTypeID( "T   " );

        var desc3 = new ActionDescriptor();

        var idUsrs = charIDToTypeID( "Usrs" );

        desc3.putBoolean( idUsrs, false );

    var idLyr = charIDToTypeID( "Lyr " );

    desc2.putObject( idT, idLyr, desc3 );

executeAction( idsetd, desc2, DialogModes.NO );

}

Here is how I got the Selection bounds in CS2

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

I tried both scripts and I can't get either to work.

The first just spits back the canvas size, like all other attempts I have tried at getting the bounding box of the mask.


The second just errors out here: var LB = activeDocument.selection.bounds; 

Error 1302: No such element

Line: 6

->  var LB = activeDocument.selection.bounds;

I am selecting the layer mask before executing.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Did you target the layer you want to get the bound of before running the scripts? If the background layer is the currently Photoshop targeted you will get the Canvas size bounds.  The is the size of a background layer it is canvas size for it does not support transparency.

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Yes, I select the layer mask.  I am NOT selecting the background.

Everything above is the code you guys just posted. I am not sure what you are talking about.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Its the layer content that is important if you have a layer mask the has bounds less then the camvas size it will make the layer bound less that canvas size.   A layer may also have a bounds smaller then a layer mask slelection bounds.  The screen  capture I posted show this if you read the Script alert messages you should see this. The middle image has a reveal all layet mask its selection boynds is canvas size.  The layers content the image is less then canvas size.

Capture.jpg

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Selection from any channel: Re: Selecting custom pixels

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

I appreciate the help.  Sorry guys, I am not an avid Photoshop or Javascript expert here in scripting.

I have tried your selection script and it errors out if I fill in the mask channel name.  I have also tried just RGB and I get the same error:

Error: Illegal Argument

Tried:

selection_from_channel("RGB");

//selection_from_channel("Msk ");

and

selection_from_channel("HL Mask");      <--- Name of the Layer Mask Channel

//selection_from_channel("Msk ");

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Are you using apple script on a mac? What you posted does not look like Adobe DOM javascript code or Action Manager javascript code? or Code r-bin has posted.

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

sz20044 

I appreciate the help.  Sorry guys, I am not an avid Photoshop or Javascript expert here in scripting.

I have tried your selection script and it errors out if I fill in the mask channel name.  I have also tried just RGB and I get the same error:

Error: Illegal Argument

Tried:

selection_from_channel("RGB");

//selection_from_channel("Msk ");

and

selection_from_channel("HL Mask");      <--- Name of the Layer Mask Channel

//selection_from_channel("Msk ");

This is not a channel name, but a four-character CharID for standard channels.

You had to do it that way.

if (selection_from_channel("Msk "))

    {

    try { var b = activeDocument.selection.bounds; } catch(e) { alert("No selection");  }

    alert(b);

    }

function selection_from_channel(ch_name)

    {

    try {

        var d = new ActionDescriptor();

        var r1 = new ActionReference();

        var r2 = new ActionReference();

        r1.putProperty(charIDToTypeID("Chnl" ), charIDToTypeID("fsel"));

        r2.putEnumerated(charIDToTypeID("Chnl"), charIDToTypeID("Chnl"), charIDToTypeID(ch_name));

        d.putReference(charIDToTypeID("null"), r1);

        d.putReference(charIDToTypeID("T   "), r2);

        executeAction(charIDToTypeID("setd"), d, DialogModes.NO);

        return true;

        }

    catch(e) { alert("No mask"); return false; }

    }


You can rewrite the function to use more understandable StringID

if (selection_from_channel("mask"))

    {

    try { var b = activeDocument.selection.bounds; } catch(e) { alert("No selection");  }

    alert(b);

    }

function selection_from_channel(ch_name)

    {

    try {

        var d = new ActionDescriptor();

        var r1 = new ActionReference();

        var r2 = new ActionReference();

        r1.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));

        r2.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID(ch_name));

        d.putReference(stringIDToTypeID("null"), r1);

        d.putReference(stringIDToTypeID("to"), r2);

        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);

        return true;

        }

    catch(e) { alert("No mask"); return false; }

    }

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Thank you, this helps!

On this same note, is there an easy way to check if a particular group is one that contains these layer masks?  Obviously having to run different code for ones that do vs ones that don't.  I know I can check to see what the activeLayer type is (for example if it is a LayerSet) ... is there a way to check if that activeLayer is a mask or contains masks?

if(doc.activeLayer.typename == 'LayerSet')

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

Look here.Re: Photoshop Scripting - Update Layers
There are some useful functions for working with a mask.

For use only for activeLayer is possible in the function has_layer_mask()
replace
     r.putIdentifier (stringIDToTypeID ("layer"), layer_id);
with

     r.putEnumerated (stringIDToTypeID ("layer"), stringIDToTypeID ("ordinal"), stringIDToTypeID ("targetEnum"));

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

How do I get the layer_id?  What's the call to get that?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Mar 29, 2019 Mar 29, 2019

Copy link to clipboard

Copied

var layer1 = activeDocument.activeLayer

var layer2 = activeDocument.layers[0]

alert(layer1.id)

alert(layer2.id)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 19, 2024 Dec 19, 2024

Copy link to clipboard

Copied

Hello! Resurrecting an old question here! @r-bin this script works perfectly one single layers, but how can I incorporate this into a loop of selected layers? This does not seem to work. Thank you!

 

 

var layers = doc.layers;
for (var i = 0; i <layers.length; i++) {
   if(hasMask(layers[i])){
      if (selection_from_channel("mask")){
         try { 
            var b = activeDocument.selection.bounds; 
         } catch(e) { alert("No selection"); }
         alert(b);
      }
   }
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 19, 2024 Dec 19, 2024

Copy link to clipboard

Copied

LATEST

Sorry the code i was showing was incorrect, this is what I was referring to... still does not work:

var layers = doc.layers;
for (var i = 0; i <layers.length; i++) {
      if (selection_from_channel("mask")){
         try { 
            var b = activeDocument.selection.bounds; 
         } catch(e) { alert("No selection"); }
         alert(b);
      }
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines