Skip to main content
sz20044
Known Participant
March 28, 2019
Answered

How to get bounding box of a layer mask?

  • March 28, 2019
  • 1 reply
  • 4055 views

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.

This topic has been closed for replies.
Correct answer r-bin

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 ");


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; }

    }

1 reply

Legend
March 28, 2019

1. Convert Mask channel to selection

2. Use selection.bounds

sz20044
sz20044Author
Known Participant
March 28, 2019

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];

JJMack
Community Expert
Community Expert
March 29, 2019

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.

// 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