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

Get layerSet size but ignore Effect layer.

Advocate ,
Aug 04, 2017 Aug 04, 2017

Copy link to clipboard

Copied

Hey guys. I found myself in a trouble. Here's a screenshot.

Screen Shot 2017-08-04 at 14.09.16.png

I need to get Group size, however, Levels effect seems to brake it:/

app.activeDocument.activeLayer.boundsNoEffects;

If Groups is selected, it returns 0 px,0 px,500 px,500 px

If LAYER is selected, it returns 125 px,200 px,375 px,300 px

So my question is - is it possible to ignore Levels Size? Because they brake my calculations, and I need to get a result 125 px,200 px,375 px,300 px if Group is selected. Is this somehow doable?

TOPICS
Actions and scripting

Views

1.3K

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

Enthusiast , Aug 27, 2017 Aug 27, 2017

Here is code without Lexicon library. I can't share library because is experimental and not done yet.

It takes 500ms per 1018 layers. And 77ms per 179 layers on my old PC 🙂

JJMack: you are wrong. This is "or" condition. I am skiping clipped layer and/or adjustment. Not clipped adjustment.

var groupIndex = app.activeDocument.activeLayer.itemIndex;

function calculateGroupSize(index){

       

    var maxBounds = {

            left : null,

            top : null,

            right : null,

            bottom

...

Votes

Translate

Translate
Adobe
Community Expert ,
Aug 04, 2017 Aug 04, 2017

Copy link to clipboard

Copied

The only way I think you can get around this is a clumsy workaround. Get the code to dupe the layer group, merge the copy of the group, get your layer bounds, then delete the duped group.

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
Enthusiast ,
Aug 26, 2017 Aug 26, 2017

Copy link to clipboard

Copied

Faster approach would be traverse all layers inside group with AM code get layer bounds and exclude some kind of layers. And then merge your bound with mathematica. (find maximum and minimum value in arrays)

This could be 10-50× faster. Reading descriptors with AM code is pretty fast. Duplicating merging and removing could take 30ms per each action. Properly written AM could do this in less than 5ms.

I will likely write this code in next days for UnSmart 2.0 script 🙂

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
Enthusiast ,
Aug 04, 2017 Aug 04, 2017

Copy link to clipboard

Copied

Maybe action manager code could return different values.

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
Engaged ,
Aug 26, 2017 Aug 26, 2017

Copy link to clipboard

Copied

Descriptor for the Group has "bounds", "boundsNoEffects" and "boundsNoMask", but each one of them sports the full bound (so in Tomas case 0,0,500,500).

No luck!

Davide

Davide Barranca
PS developer and author => www.ps-scripting.com

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 ,
Aug 26, 2017 Aug 26, 2017

Copy link to clipboard

Copied

In your group you have clipped the levels adjustment layer levels 1 to  the shape or smart object layer LAYER.  LAYER has a bounds less than canvas size.  The levels adjustment does not effect the any layers below that layer LAYER because it is clipped to the layer LAYER.  An alternate method  would be instead of clipping the  adjustment layer levels 1 you could mask the adjustment layer to the layer LAYER transparency. You could do the same to the clipped Adjustment levels 1 even.   Either way the bounds of the adjustment layer levels 1 would have the same bounds as layer LAYER.  So would the group.

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
Advocate ,
Aug 26, 2017 Aug 26, 2017

Copy link to clipboard

Copied

JJMack​ I am having real trouble understanding what you wrote.

And Davide Barranca​ is right, those methods still return same size as the canvas.

Jarda Bereza​ might be on a track of making it work. I thought of traversing all the layers and collecting their bounding box size and then calculating the overall size, but it smells as a hacky way to do so. If it could be done with AM logic, that would be great. However, I am rather new to PSD scripting and I find AM to be rather tricky t get a grasp on.

Jarda Bereza​ if you figure out the way to do that with AM, would you be willing to share your workflow?

Thanks.

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 ,
Aug 26, 2017 Aug 26, 2017

Copy link to clipboard

Copied

Let me try a different way  to explain way I wrote and include some screen captures.

An adjustment layer bounds is the same as the document canvas size unless masked and applies to all lower layer.  You constrain an adjustment to fewer layer be segregating it within a layer group and clipping it to a particular layer.  You can also constrain the adjustment to a selection via a layer mask.   Transparency can change a layer bounds.  The layer bounds will be the bounds of pixels in the layer mask.

To me it looks like you only want the levels adjustment layer to apply to the layer named LAYER.  There are many ways to do that....

Here is a little script that show  the active layer size bounds and position relative to the canvas.  I will use it on layer Group see the differences,

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

}

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
Enthusiast ,
Aug 27, 2017 Aug 27, 2017

Copy link to clipboard

Copied

Try this:

Seems to work for me. You will need replace some function from lx. library with your own. But is obvious what it should do.

And it should be very very fast. It uses linear layers traversing.

#include A:\programovani\PSDmagic\[Lx]\Lexicon-0.1.jsxinc

var layerID = lx.getSelectedLayersId();

calculateGroupSize(layerID);

function calculateGroupSize(layerID){

       

    var maxBounds = {

            left : null,

            top : null,

            right : null,

            bottom : null

    }

   

    var index = lx.convertLayerIdToIndex(layerID);

    for(var i = index-1, level=0; level >= 0 ; i--){

        var desc = lx.getLayerDescriptor(i); // i = index

        var clipped = desc.getBoolean(stringIDToTypeID('group'));

        var isAdjustmentLayer = desc.getInteger(stringIDToTypeID('layerKind')) === 2;

       

        if(clipped || isAdjustmentLayer){continue;} //skip this layer

       

        var layerSection = typeIDToStringID(desc.getEnumerationValue(stringIDToTypeID('layerSection')));

        if(layerSection==="layerSectionStart"){

            level++

        }

        else if(layerSection==="layerSectionEnd"){

            level--

        }

        else{

            var bounds = desc.getObjectValue(stringIDToTypeID('bounds'));

            if(maxBounds.left === null) {maxBounds.left = bounds.getUnitDoubleValue(stringIDToTypeID('left'));}

            if(maxBounds.top === null) {maxBounds.top = bounds.getUnitDoubleValue(stringIDToTypeID('top'));}

            if(maxBounds.right === null) {maxBounds.right = bounds.getUnitDoubleValue(stringIDToTypeID('right'));}

            if(maxBounds.bottom === null) {maxBounds.left = bounds.getUnitDoubleValue(stringIDToTypeID('bottom'));}

              

            maxBounds.left = Math.min(maxBounds.left, bounds.getUnitDoubleValue(stringIDToTypeID('left')));

            maxBounds.top =  Math.min(maxBounds.top, bounds.getUnitDoubleValue(stringIDToTypeID('top')));

            maxBounds.right =  Math.max(maxBounds.right, bounds.getUnitDoubleValue(stringIDToTypeID('right')));

            maxBounds.bottom =  Math.max(maxBounds.bottom, bounds.getUnitDoubleValue(stringIDToTypeID('bottom')));

        }

    }

    return maxBounds;

}

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 ,
Aug 27, 2017 Aug 27, 2017

Copy link to clipboard

Copied

I do not have your script library files so I can not test that code,  It look like it skips adjustment layers if clipped.  In his layered document it does not look like the  levels 1 adjustment layer is clipped its an adjustment layer above layer LAYER in layer group Group.

Screen+Shot+2017-08-04+at+14.09.16.png

not

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
Advocate ,
Aug 27, 2017 Aug 27, 2017

Copy link to clipboard

Copied

That looks interesting, but hard to test without your lx library. Any chance you could share 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
Enthusiast ,
Aug 27, 2017 Aug 27, 2017

Copy link to clipboard

Copied

Here is code without Lexicon library. I can't share library because is experimental and not done yet.

It takes 500ms per 1018 layers. And 77ms per 179 layers on my old PC 🙂

JJMack: you are wrong. This is "or" condition. I am skiping clipped layer and/or adjustment. Not clipped adjustment.

var groupIndex = app.activeDocument.activeLayer.itemIndex;

function calculateGroupSize(index){

       

    var maxBounds = {

            left : null,

            top : null,

            right : null,

            bottom : null

    }

    for(var i = index-1, level=0; level >= 0 ; i--){

        var desc = getLayerDescriptor(i); // i = index

        var clipped = desc.getBoolean(stringIDToTypeID('group'));

        var isAdjustmentLayer = desc.getInteger(stringIDToTypeID('layerKind')) === 2;

       

        if(clipped || isAdjustmentLayer){continue;} //skip this layer

       

        var layerSection = typeIDToStringID(desc.getEnumerationValue(stringIDToTypeID('layerSection')));

        if(layerSection==="layerSectionStart"){

            level++

        }

        else if(layerSection==="layerSectionEnd"){

            level--

        }

        else{

            var bounds = desc.getObjectValue(stringIDToTypeID('bounds'));

            if(maxBounds.left === null) {maxBounds.left = bounds.getUnitDoubleValue(stringIDToTypeID('left'));}

            if(maxBounds.top === null) {maxBounds.top = bounds.getUnitDoubleValue(stringIDToTypeID('top'));}

            if(maxBounds.right === null) {maxBounds.right = bounds.getUnitDoubleValue(stringIDToTypeID('right'));}

            if(maxBounds.bottom === null) {maxBounds.left = bounds.getUnitDoubleValue(stringIDToTypeID('bottom'));}

              

            maxBounds.left = Math.min(maxBounds.left, bounds.getUnitDoubleValue(stringIDToTypeID('left')));

            maxBounds.top =  Math.min(maxBounds.top, bounds.getUnitDoubleValue(stringIDToTypeID('top')));

            maxBounds.right =  Math.max(maxBounds.right, bounds.getUnitDoubleValue(stringIDToTypeID('right')));

            maxBounds.bottom =  Math.max(maxBounds.bottom, bounds.getUnitDoubleValue(stringIDToTypeID('bottom')));

           

        }

    }

    return maxBounds;

}

var getLayerDescriptor = function (index) { //todo reference param

    var ref = new ActionReference(); 

    var idLyr = charIDToTypeID( "Lyr " );

            ref.putIndex( idLyr, index );

    var desc = executeActionGet(ref);

    return desc;

}

var bounds = calculateGroupSize(groupIndex);

alert("\n left: " + bounds.left +"\n top: " + bounds.top +"\n right: " + bounds.right +"\n bottom: " + bounds.bottom);

.

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 ,
Aug 27, 2017 Aug 27, 2017

Copy link to clipboard

Copied

Yes I do not know javascript so much of the code I do not understand.  I jumped to the wrong conclusion.  Most of the javascript code where I see .getxxx(yyyy) i have to take on faith or guess.  Can't guess right all the time.

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
Advocate ,
Sep 05, 2017 Sep 05, 2017

Copy link to clipboard

Copied

Appologies for taking long time to reply Jarda Bereza​

I jumped to conclusion too fast. Script has crashing if I had Background layer in the document. Once I removed it, it seems to work.

Will give more testing to it.

Thanks man.

Unfortunately, script crashes on var desc = executeActionGet(ref); with error Error 8800: General Photoshop error occurred. This functionality may not be available in this version of Photoshop. However, I have layerSet "Group" selected in the dome before executing the script.

Script seems to run fine if I have shape layer selected, but, unfortunately, crashes with layerSet selected.

Any chance you know why?

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
Enthusiast ,
Sep 05, 2017 Sep 05, 2017

Copy link to clipboard

Copied

maybe background layer issue

increment index by +1 at row 53 if background layer exists.

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
Advocate ,
Sep 05, 2017 Sep 05, 2017

Copy link to clipboard

Copied

LATEST

yeap, seems as if background layer was messing it up.

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