Copy link to clipboard
Copied
I am trying to script this. I want to be able to trim a layer, then expand the canvas by a set amount. Then reveal the 'whole layer' below. I can do all of this, but the issue I have is I need to trim a layer, but keep the deleted pixels of the layer underneath.
My method prior to using trim is to hide the other layers then 'trim'
Un hiding the layer then use reveal doesn't work as it has been deleted during trim How can I lock a layer so that this is protected?
Matt
Copy link to clipboard
Copied
You can use the ActionManager code (as recorded with ScriptingListener.plugin) recorded when using the Crop Tool.
Copy link to clipboard
Copied
I'm fine using that above, but I don't think helps with what I am trying to achieve.
Something like this
Layer1 Main
Layer2 Background (Now Hide it)
Select Layer 1 Main
trim basing trim on transparent pixels
Unhide Layer 2 Background
Reveal all
Copy link to clipboard
Copied
Just use the bounding box to determine the intended Crop and use the Crop Tool with »Delete Cropped Pixels« unchecked.
Copy link to clipboard
Copied
Do you mean manually cropping? Can the crop tool, crop out the transparent pixels?
Copy link to clipboard
Copied
Do you mean manually cropping?
Of course not, in post 1 I specifically referred to the ActionManager code.
Can the crop tool, crop out the transparent pixels?
One can determine a Layer’s bounds and feed those values to the AM code for the Crop Tool.
Copy link to clipboard
Copied
Understood, that gives me something to work on, many thanks! I'll let you know how I get on.
Copy link to clipboard
Copied
Good luck!
Copy link to clipboard
Copied
I'm almost there, but have you a v
app.activeDocument.crop(["1841","2648","3187","3445"]);
where the pixels don't get deleted?
Copy link to clipboard
Copied
Don’t use the method »crop«, use the ActionManager code created when cropping.
Copy link to clipboard
Copied
When cropping with the Crop Tool that is.
Copy link to clipboard
Copied
Sorry for all the questions, I have this
var X = descBounds.getUnitDoubleValue(stringIDToTypeID('left'));
var Y = descBounds.getUnitDoubleValue(stringIDToTypeID('top'));
var W = descBounds.getUnitDoubleValue(stringIDToTypeID('right'));
var H = descBounds.getUnitDoubleValue(stringIDToTypeID('bottom'));
I thought i'd replace the numbers with X,Y,W,H but i'm not sure how to put it in? More use to applescript
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idTop, idPxl, 2309.843750 );
var idLeft = charIDToTypeID( "Left" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idLeft, idPxl, 2324.187500 );
var idBtom = charIDToTypeID( "Btom" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idBtom, idPxl, 3862.843750 );
var idRght = charIDToTypeID( "Rght" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idRght, idPxl, 3359.187500 );
Copy link to clipboard
Copied
Here it is in full, its all borrowed. So not to clean as yet.
#target photoshop
main();
function main(){
if(!documents.length) return;
var Info = getNamesPlusIDs().sort();
var Name = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var file = new File(Folder.desktop + "/" + Name + ".txt");
file.open("w", "TEXT", "????");
$.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
for(var a in Info) file.writeln(Info.toString());
file.close();
}
function getNamesPlusIDs(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;
var Names=[];
try{
activeDocument.backgroundLayer;
var i = 0; }catch(e){ var i = 1; };
for(i;i<count;i++){
if(i == 0) continue;
ref = new ActionReference();
ref.putIndex( charIDToTypeID( 'Lyr ' ), i );
var desc = executeActionGet(ref);
var layerName = desc.getString(charIDToTypeID( 'Nm ' ));
var Id = desc.getInteger(stringIDToTypeID( 'layerID' ));
if(layerName.match(/^<\/Layer group/) ) continue;
var vMask = desc.getBoolean(stringIDToTypeID('hasVectorMask' ));
try{
var adjust = typeIDToStringID(desc.getList (stringIDToTypeID('adjustment')).getClass (0));
if(vMask == true){
adjust = false;
var Shape = true;
}
}catch(e){var adjust = false; var Shape = false;}
var layerType = typeIDToStringID(desc.getEnumerationValue( stringIDToTypeID( 'layerSection' )));
var isLayerSet =( layerType == 'layerSectionContent') ? false:true;
var Vis = desc.getBoolean(stringIDToTypeID( 'visible' ));
var descBounds = executeActionGet(ref).getObjectValue(stringIDToTypeID( "bounds" ));
var X = descBounds.getUnitDoubleValue(stringIDToTypeID('left'));
var Y = descBounds.getUnitDoubleValue(stringIDToTypeID('top'));
var W = descBounds.getUnitDoubleValue(stringIDToTypeID('right'));
var H = descBounds.getUnitDoubleValue(stringIDToTypeID('bottom'));
//var W = XW - X;
//var H = XH - Y;
var idCrop = charIDToTypeID( "Crop" );
var desc290 = new ActionDescriptor();
var idT = charIDToTypeID( "T " );
var desc291 = new ActionDescriptor();
var idTop = charIDToTypeID( "Top " );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idTop, idPxl, 2309.843750 );
var idLeft = charIDToTypeID( "Left" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idLeft, idPxl, 2324.187500 );
var idBtom = charIDToTypeID( "Btom" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idBtom, idPxl, 3862.843750 );
var idRght = charIDToTypeID( "Rght" );
var idPxl = charIDToTypeID( "#Pxl" );
desc291.putUnitDouble( idRght, idPxl, 3359.187500 );
var idRctn = charIDToTypeID( "Rctn" );
desc290.putObject( idT, idRctn, desc291 );
var idAngl = charIDToTypeID( "Angl" );
var idAng = charIDToTypeID( "#Ang" );
desc290.putUnitDouble( idAngl, idAng, 0.000000 );
var idDlt = charIDToTypeID( "Dlt " );
desc290.putBoolean( idDlt, false );
var idcropAspectRatioModeKey = stringIDToTypeID( "cropAspectRatioModeKey" );
var idcropAspectRatioModeClass = stringIDToTypeID( "cropAspectRatioModeClass" );
var idtargetSize = stringIDToTypeID( "targetSize" );
desc290.putEnumerated( idcropAspectRatioModeKey, idcropAspectRatioModeClass, idtargetSize );
var idWdth = charIDToTypeID( "Wdth" );
var idRlt = charIDToTypeID( "#Rlt" );
desc290.putUnitDouble( idWdth, idRlt, 28913.385827 );
var idHght = charIDToTypeID( "Hght" );
var idRlt = charIDToTypeID( "#Rlt" );
desc290.putUnitDouble( idHght, idRlt, 43370.078740 );
executeAction( idCrop, desc290, DialogModes.NO );
app.activeDocument.crop([X,Y,W,H]);
//if(Vis && !isLayerSet && !adjust) Names.push([[layerName],
, , , ]); };
return Names;
};
Copy link to clipboard
Copied
So does this Script do what you want?
Because I fail to see how you feed the bounds to the AM cropping-code but you use the method »crop« again in the line
app.activeDocument.crop([X,Y,W,H]);
Copy link to clipboard
Copied
Sorry I messed the code up above as I left some lines in. This appears to be working now, (for the moment) I will need to add some other lines in to hide all other layers except 'main image'.
Then after that I can expand the canvas to a set ratio etc to reveal the original background.
#target photoshop
main();
function main(){
if(!documents.length) return;
var Info = getNamesPlusIDs().sort();
var Name = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var file = new File(Folder.desktop + "/" + Name + ".txt");
file.open("w", "TEXT", "????");
$.os.search(/windows/i) != -1 ? file.lineFeed = 'windows' : file.lineFeed = 'macintosh';
for(var a in Info) file.writeln(Info.toString());
file.close();
}
function getNamesPlusIDs(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
var count = executeActionGet(ref).getInteger(charIDToTypeID('NmbL')) +1;
var Names=[];
try{
activeDocument.backgroundLayer;
var i = 0; }catch(e){ var i = 1; };
for(i;i<count;i++){
if(i == 0) continue;
ref = new ActionReference();
ref.putIndex( charIDToTypeID( 'Lyr ' ), i );
var desc = executeActionGet(ref);
var layerName = desc.getString(charIDToTypeID( 'Nm ' ));
var Id = desc.getInteger(stringIDToTypeID( 'layerID' ));
if(layerName.match(/^<\/Layer group/) ) continue;
var vMask = desc.getBoolean(stringIDToTypeID('hasVectorMask' ));
try{
var adjust = typeIDToStringID(desc.getList (stringIDToTypeID('adjustment')).getClass (0));
if(vMask == true){
adjust = false;
var Shape = true;
}
}catch(e){var adjust = false; var Shape = false;}
var layerType = typeIDToStringID(desc.getEnumerationValue( stringIDToTypeID( 'layerSection' )));
var isLayerSet =( layerType == 'layerSectionContent') ? false:true;
var Vis = desc.getBoolean(stringIDToTypeID( 'visible' ));
var descBounds = executeActionGet(ref).getObjectValue(stringIDToTypeID( "bounds" ));
var X = descBounds.getUnitDoubleValue(stringIDToTypeID('left'));
var Y = descBounds.getUnitDoubleValue(stringIDToTypeID('top'));
var W = descBounds.getUnitDoubleValue(stringIDToTypeID('right'));
var H = descBounds.getUnitDoubleValue(stringIDToTypeID('bottom'));
//var W = XW - X;
//var H = XH - Y;
// =======================================================
var idslct = charIDToTypeID( "slct" );
var desc2220 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref95 = new ActionReference();
var idcropTool = stringIDToTypeID( "cropTool" );
ref95.putClass( idcropTool );
desc2220.putReference( idnull, ref95 );
var iddontRecord = stringIDToTypeID( "dontRecord" );
desc2220.putBoolean( iddontRecord, true );
var idforceNotify = stringIDToTypeID( "forceNotify" );
desc2220.putBoolean( idforceNotify, true );
executeAction( idslct, desc2220, DialogModes.NO );
// =======================================================
var idCrop = charIDToTypeID( "Crop" );
var desc2221 = new ActionDescriptor();
var idT = charIDToTypeID( "T " );
var desc2222 = new ActionDescriptor();
var idTop = charIDToTypeID( "Top " );
var idPxl = charIDToTypeID( "#Pxl" );
desc2222.putUnitDouble( idTop, idPxl, Y );
var idLeft = charIDToTypeID( "Left" );
var idPxl = charIDToTypeID( "#Pxl" );
desc2222.putUnitDouble( idLeft, idPxl, X );
var idBtom = charIDToTypeID( "Btom" );
var idPxl = charIDToTypeID( "#Pxl" );
desc2222.putUnitDouble( idBtom, idPxl, H );
var idRght = charIDToTypeID( "Rght" );
var idPxl = charIDToTypeID( "#Pxl" );
desc2222.putUnitDouble( idRght, idPxl, W );
var idRctn = charIDToTypeID( "Rctn" );
desc2221.putObject( idT, idRctn, desc2222 );
var idAngl = charIDToTypeID( "Angl" );
var idAng = charIDToTypeID( "#Ang" );
desc2221.putUnitDouble( idAngl, idAng, 0.000000 );
var idDlt = charIDToTypeID( "Dlt " );
desc2221.putBoolean( idDlt, false );
var idcropAspectRatioModeKey = stringIDToTypeID( "cropAspectRatioModeKey" );
var idcropAspectRatioModeClass = stringIDToTypeID( "cropAspectRatioModeClass" );
var idtargetSize = stringIDToTypeID( "targetSize" );
desc2221.putEnumerated( idcropAspectRatioModeKey, idcropAspectRatioModeClass, idtargetSize );
executeAction( idCrop, desc2221, DialogModes.NO );
};
return Names;
};
Copy link to clipboard
Copied
This is AM code to hide the other Layers (other than the active Layer):
hideOthers ();
////// toggle visibility of others //////
function hideOthers () {
// =======================================================
var idShw = charIDToTypeID( "Shw " );
var desc10 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var list4 = new ActionList();
var ref7 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref7.putEnumerated( idLyr, idOrdn, idTrgt );
list4.putReference( ref7 );
desc10.putList( idnull, list4 );
var idTglO = charIDToTypeID( "TglO" );
desc10.putBoolean( idTglO, true );
executeAction( idShw, desc10, DialogModes.NO );
};
Copy link to clipboard
Copied
I do not get what you are doing? I open a test document it has five layers. A white background layer and four normal layers. Theses are smaller black layers each having a different color center. I run your script the canvas is trimmed to match one of my black layers. Expanding the canvas I see the background layer has been converted to a normal "layer 0" and none of the black bored las have hat the borders trimmed. It that what what you wanted.
I thought you wanted to trim layers. That what I tried to do in may script, But the magic wand will select empty pixels as well as color pixels. I was hoping could use the magic wand the it would fail to make a selection if clicked on an empty pixels. So I could catch the error and move the sample point till I found an actual pixel to sample. Instead all I cot do Is take a shot in the dark and sample some points on a layers bounds. A hit or miss approach. Still my script trims my simple black borders however If I rotate the layers a bit my sampling points may miss the black.
Copy link to clipboard
Copied
https://www.dropbox.com/s/8ojnt5ersx11e5l/WW_001.psd?dl=0
I've added a sample file here. The script isn't complete, but the idea is after the trim to the bracelets I will then expand the canvas to a ratio of 2:3, then the distance between the edge of the item to the border is 5% of the width of the image at trim point. Although the "layer 1" is grey it is textured. Hence I need to keep the "layer 1" in tact.
Hope that clears up what I am trying to achieve,
Matt
Copy link to clipboard
Copied
Increasing the Canvas Size through Script is not a problem, though, is it?
Copy link to clipboard
Copied
Should be ok, just got to have the time to figure it out, I had something similar running before via applescript. Just need to try an reconfigure.
Copy link to clipboard
Copied
Mattmcquiff wrote:
https://www.dropbox.com/s/8ojnt5ersx11e5l/WW_001.psd?dl=0
The script isn't complete, but the idea is after the trim to the bracelets I will then expand the canvas to a ratio of 2:3, then the distance between the edge of the item to the border is 5% of the width of the image at trim point. Although the "layer 1" is grey it is textured. Hence I need to keep the "layer 1" in tact.
Matt
If layer 1 is a solid color all you need is its color. The problem I see in your example PSD is that it look like you tried to trim bracelet layer using the magic wand tool not it contiguous mode with the tolerance value set too low to trim a background the had various shades of gray. Because the tolerance value was set to low the layer was not trimmed to the object. It is now not possible to get the size and aspect ratio of the layers object so there is no way to calculate the the 2:3 aspect ratio layer size required. The layer's object has a landscape aspect ratio. Putting it on a Portrait 2:3 aspect ratio canvas would have very large top and bottom boarders that could also exceed the original canvas size height.
If you place a black background in and target the bracelet layer and do a Ctrl+T free transform. You will be able the see where the layer was trimmed to and if you move the bracelet layer you may be able to see the low opacity gray pixels that were not trimmed.
Copy link to clipboard
Copied
Forgive me if Im not following, I shall attempt to explain again. Firstly the "layer 1" is NOT a solid colour, but a textured background. (also aware that in the sample it may not be big enough.
What we know
After the crop looking at the Main Image layer we know this
Height of Current layer = H
Width of Current layer = W
BorderIncrease is = 120(%)
Target height 1530 or tHeight
Target width 1020 or tWidth
set theTargetRatio to tHeight/tWidth
If (H/W) is less than theTargetRatio then
(increase the width first)
set canvas width to W x (120/100) =1596px anchor point center
Set image width to tWidth (1020) points without resampling
set canvas height to tHeight (1530) points without resampling.
else >>then (increase height first) etc...
In the sample above I realise that the layer 1 isn't larger enough, however it does achieve what I am looking for.
I hope this explains what I am attempting to do.
Copy link to clipboard
Copied
To tell the truth I do not know what your after. Your script posted is coded to process many layers. Not just two layers like in your example PSD file. IMO how one would address one product vs many product would most likely be very different code.
In your previous write you stated the your target was a 2:3 aspect ratio which your 1020:1530 ratio is however how you came up with those number is beyond me. If you resize the Main Image layer to fit you would be resampling the layer.
You also write about setting canvas size without resampling. Changing a document canvas size never involves resampling. In fact only a background layer could or would see any changes to its pixels. For the background layer is a special Photoshop layer that does not support transparency. A background layer is always canvas size. A background layer can have pixels added and removed when a document canvas size is changed. No other layer pixels will be changes at all. Only its position relative to the document canvas may change and the document canvas size may act like a clipping mask for other layers. You have no background so your Layer 1 2000px bt 2000px will be clipped to your 1020px by 1530px Canvas size.
The PSD you posted Main image layer bounds are 1330px wide and 486 px in height. If you set the document canvas width to 1020 you would be clipping your product width and adding much texture on top and bottom of your product..
The size I came up with has one of your numbers 1596 that is what the final width should be and the height would be 2394 your texture would fill the width but not the height.
Copy link to clipboard
Copied
JJMack wrote:
To tell the truth I do not know what your after. Your script posted is coded to process many layers. Not just two layers like in your example PSD file. IMO how one would address one product vs many product would most likely be very different code.
The code isn't finalise, typically the PSD file will have 4 layers, it should only effect the layer selected as it hides all others (the script was found on the net)
JJMack wrote:
In your previous write you stated the your target was a 2:3 aspect ratio which your 1020:1530 ratio is however how you came up with those number is beyond me. If you resize the Main Image layer to fit you would be resampling the layer.
Sorry I shouldn't have included this this number is used in a later script to scale the picture to 1020px x 1530px Not needed at this stage but as you mention this is the same as 2:3
JJMack wrote:
You also write about setting canvas size without resampling. Changing a document canvas size never involves resampling. In fact only a background layer could or would see any changes to its pixels. For the background layer is a special Photoshop layer that does not support transparency. A background layer is always canvas size. A background layer can have pixels added and removed when a document canvas size is changed. No other layer pixels will be changes at all. Only its position relative to the document canvas may change and the document canvas size may act like a clipping mask for other layers. You have no background so your Layer 1 2000px bt 2000px will be clipped to your 1020px by 1530px Canvas size.
Canvas size resampling I meant to add that to the image size. The Canvas is not to be clipped to 1020px x 1530px but 2 inches x 3 inchs or 20 points x 30 points (just a measurement not exact pixels)
JJMack wrote:
The PSD you posted Main image layer bounds are 1330px wide and 486 px in height. If you set the document canvas width to 1020 you would be clipping your product width and adding much texture on top and bottom of your product..
The document canvas width is not set to 1020 from 1330px but is changed from 1330px to 1330px +20% 1596px
Then in Image Size I change the value of the width to 2" without resampling.
Then go into Canvas size select inches and change the height to 3"
The image is then in the ratio of 2(w):3(h) with no loss in image quality and no clipping.
JJMack wrote:
The size I came up with has one of your numbers 1596 that is what the final width should be and the height would be 2394 your texture would fill the width but not the height.
The figures you got are correct the final image is 1596 x 2394, and as per the previous post yes the layer 1 is not larger enough to fill the canvas (although it will be once the original image is correct). The idea is that the item is framed with "layer 1" Where it is not stretched to fit the background to keep it as it is.
I've updated the file at the same location, I've add some stuff to the layer 1 just to help see that I need to keep it scaled the same but allowed to be cropped.
Hope that starts to make sense. Make sense in my head not when try typing it
Copy link to clipboard
Copied
Mattmcquiff wrote:
The document canvas width is not set to 1020 from 1330px but is changed from 1330px to 1330px +20% 1596px
Then in Image Size I change the value of the width to 2" without resampling.
Then go into Canvas size select inches and change the height to 3"
The image is then in the ratio of 2(w):3(h) with no loss in image quality and no clipping.
I think you a bit confused about thing work in Photoshop.
The document canvas was 2000px by 2000px????
It seems like what you think your doing is adding width to your Main Image layer. That is possible but not using image size.
In the image size dialog if you un-check Resample in the print size area you can set one value width, height or resolution. When you set one Photoshop will calculate the other two. The net result is not a single pixel is change all that happens is the document resolution has been to a different resolution. A document only has one resolution. And its Print size size in now 2" x 2" at some resolution for you started with a square canvas. The document composite image has not changes at all. The canvas will still be 2000px by 2000px and its resolution will be 1000DPI.
If you use canvas size and set canvas height to 3" the canvas size will be 2" wide and 3" high since you do not have a background layer not a singe pixel will change be add or deleted. Your Layer 1 will be canvas width and 1/2" down from the top of the canvas and 1/2" up from the canvas bottom.
The document canvas size is 2000px wide 3000px high at 1000dpi. 2" by 3" however all the canvas is not filled with pixels the image you have is 2000px by 2000px at 1000dpi 2"x2" of the canvas area is filled with pixels.
As it is the main Image layer is centered horizontal over the canvas and a little above vertical center. Its easy to align a layer over the document canvas center. You then use canvas size and set 1596px wide and 2394px high and saved out a jpeg. you would have want you want the empty canvas will be filled with white for jpeg does not support transparence. You then back up in history to undo the canvas size change. The Canvas size changed cropped the document width and added empty canvas to the document height.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now