Copier le lien dans le Presse-papiers
Copié
Hey guys. I found myself in a trouble. Here's a screenshot.
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?
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
Copier le lien dans le Presse-papiers
Copié
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.
Copier le lien dans le Presse-papiers
Copié
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 🙂
Copier le lien dans le Presse-papiers
Copié
Maybe action manager code could return different values.
Copier le lien dans le Presse-papiers
Copié
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
Copier le lien dans le Presse-papiers
Copié
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.
Copier le lien dans le Presse-papiers
Copié
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.
Copier le lien dans le Presse-papiers
Copié
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,
// 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 );
}
Copier le lien dans le Presse-papiers
Copié
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;
}
Copier le lien dans le Presse-papiers
Copié
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.
not
Copier le lien dans le Presse-papiers
Copié
That looks interesting, but hard to test without your lx library. Any chance you could share that?
Copier le lien dans le Presse-papiers
Copié
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);
.
Copier le lien dans le Presse-papiers
Copié
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.
Copier le lien dans le Presse-papiers
Copié
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?
Copier le lien dans le Presse-papiers
Copié
maybe background layer issue
increment index by +1 at row 53 if background layer exists.
Copier le lien dans le Presse-papiers
Copié
yeap, seems as if background layer was messing it up.
Trouvez plus d’idées, d’événements et de ressources dans la nouvelle communauté Adobe
Explorer maintenant