Skip to main content
Known Participant
May 1, 2016
Question

Guides and cropping

  • May 1, 2016
  • 15 replies
  • 4551 views

Hi,

I have CS6, the extendscript tool, and am thinking of Photoshop.  Of course, guides snap to the edges of my images. If I place 4 guides around my photo, and drag the crop tool; it will snap to each of these guides.  Is it possible to write a script to: First, automatically place 3 guides on my image: one on the top edge, one of the right side, and one on the bottom edge?  (then the script would have to pause or end, while I  manually place the last on the left side.)  And, then, if the positions of these guides are "known" to Photoshop; can a script place the crop tool on the rectangle defined by these 4 guides?

I can create an action that does the first part: that places 3 guides, automatically on the edges.  Once I place the 4th guide, the crop tool will automatically size itself to fit right on the rectangles outlined by the guide.  But I have to do a lot of zooming and panning to place the 4th guide, to get it just right.  I notice, however, that if I click with the magnetic lasso tool--in the general vicinity of where the 4th guide needs to go--that I can zoom in, and Photoshop keeps the zoom focused on that first click of the lasso tool.  I can escape out of it, place a guide there, then, the crop tool seems to automatically go where I want it to.

I am just wondering how aware Photoshop is of the positions of the guides, the edges of the images, and if it stores this information to variables, that in turn could be used when placing the crop tool.

Thanks, Steve

This topic has been closed for replies.

15 replies

Known Participant
May 2, 2016

Chuck Uebele:  Sounds like I need get those values into and array and sort them, first? Or at least get it in the right order before stuffing the variables and doing the executeAction( idCrop, desc7, DialogModes.NO );

Thanks, Steve

999tevashkevich
Known Participant
May 2, 2016

The only problem I see with this is maybe deciding which one you want to be your variable guide (unless you're always going to have it be the top horizontal one)

I have to go to work in a bit but I'll test some stuff tonight and maybe see what I can do. (i'll probably just end up giving you a GUI that you can select "leave Top/Left/Right/Bottom" and go from there honestly)

Known Participant
May 2, 2016

Known Participant
May 2, 2016

Hello c.pfaffenbichler and JJMack:  Thank you for your suggestions.  c.pfaffenbichler:  I am not using layer.bounds because that would give me the outline of the layer and I need to crop a subset of some images?   On the other hand, maybe layer.bounds could tell me where the first three sides of the rectangles are, without having to draw guides?  While I am new to scripting for Adobe Photoshop, I have printed out the manuals!!!  JJMack, yours is just what I had in mind, however, I am running into some issues:

1. I have a number of photos so work on, all different sizes, and the action that I recorded only knows how to place the guides in the positions corresponding to the size of the first photo that I worked on.  So I need to figure out how to use a script to determine programmatically (a) the dimensions of the photo and the 4 coordinates of each photo, so (b) and then, based on that information,  either find the layer.bounds or draw 3 guides, programmatically, and then crop

2. Then for the pause, I am not sure how to do that.  An alert will not let me draw the 4th guide, until I hit OK.  And a sleep function might not give me enough time.  Is there a true wait function, one that will still let me do stuff in Photoshop until I am done and click OK?  Otherwise I could break up my script into two parts.

3. Before I tried your code, c.pfaffenbichler, I placed 4 guides on the photo, top bottom left and right.  (To me, your code looks like something, produced by scriptListener?)  Sometimes the code runs until it gets to the very last line, where it becomes orange and stops at: executeAction( idCrop, desc7, DialogModes.NO );  Other times, the code runs without stopping. I don't know why; but it does not crop.  So this is a work in progress.

4. I have a feeling that somewhere in your code, c.pfaffenbichler, are the programmatic lines that identify the position and dimensions of the photo?  So I will need to get up to speed with scriptListener and its constants to find out what's happening there.  Along these lines, I started to add $.writeln's in your code to see what it is capturing. Neat!

thank you very much,

Steve

999tevashkevich
Known Participant
May 2, 2016

Are you only wanting the guides to snap to the visible canvas edges or (as you said in 1. above) the bounds of the selected layer?

I might be able to help you if you give me a visual reference to work off of

c.pfaffenbichler
Community Expert
Community Expert
May 2, 2016

What are you  trying to achieve?

Why use guides at all instead of the Layer’s bounds?

This would crop to 4 guides, changing DialogModes.NO to DialogModes.ALL would cause the Crop Tool not to be applied but remain active.

// 2014, use at your own risk;

#target photoshop

if (app.documents.length > 0) {main()};

////// function //////

function main () {

// set to pixels and 72ppi;

var myDocument = app.activeDocument;

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var originalResolution = myDocument.resolution;

myDocument.resizeImage (null, null, 72, ResampleMethod.NONE);

if (myDocument.guides.length == 4) {

// get guides;

var theVert = new Array;

var theHor = new Array;

for (var m = 0; m < myDocument.guides.length; m++) {

  if (myDocument.guides.direction == Direction.HORIZONTAL) {theVert.push(myDocument.guides.coordinate)}

  else {theHor.push(myDocument.guides.coordinate)}

  };

// crop;

if (theHor.length == 2 && theVert.length == 2) {

  cropThis(Number(Math.min(theVert[0], theVert[1])), Number(Math.min(theHor[0],theHor[1])), Number(Math.max(theVert[0], theVert[1])), Number(Math.max(theHor[0],theHor[1])))

  };

};

// reset;

app.preferences.rulerUnits = originalRulerUnits;

myDocument.resizeImage (null, null, originalResolution, ResampleMethod.NONE);

};

////// crop //////

function cropThis (x1, x2, x3, x4) {

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

var idCrop = charIDToTypeID( "Crop" );

    var desc7 = new ActionDescriptor();

    var idT = charIDToTypeID( "T   " );

        var desc8 = new ActionDescriptor();

        var idTop = charIDToTypeID( "Top " );

        var idRlt = charIDToTypeID( "#Rlt" );

        desc8.putUnitDouble( idTop, idRlt, x1 );

        var idLeft = charIDToTypeID( "Left" );

        var idRlt = charIDToTypeID( "#Rlt" );

        desc8.putUnitDouble( idLeft, idRlt, x2 );

        var idBtom = charIDToTypeID( "Btom" );

        var idRlt = charIDToTypeID( "#Rlt" );

        desc8.putUnitDouble( idBtom, idRlt, x3 );

        var idRght = charIDToTypeID( "Rght" );

        var idRlt = charIDToTypeID( "#Rlt" );

        desc8.putUnitDouble( idRght, idRlt, x4 );

    var idRctn = charIDToTypeID( "Rctn" );

    desc7.putObject( idT, idRctn, desc8 );

    var idAngl = charIDToTypeID( "Angl" );

    var idAng = charIDToTypeID( "#Ang" );

    desc7.putUnitDouble( idAngl, idAng, 0.000000 );

    var idDlt = charIDToTypeID( "Dlt " );

    desc7.putBoolean( idDlt, false );

    var idcropAspectRatioModeKey = stringIDToTypeID( "cropAspectRatioModeKey" );

    var idcropAspectRatioModeClass = stringIDToTypeID( "cropAspectRatioModeClass" );

    var idtargetSize = stringIDToTypeID( "targetSize" );

    desc7.putEnumerated( idcropAspectRatioModeKey, idcropAspectRatioModeClass, idtargetSize );

executeAction( idCrop, desc7, DialogModes.NO );

};

Chuck Uebele
Community Expert
Community Expert
May 2, 2016

I was trying to figure out how to get the location. Tried a bunch of stuff, but didn't try coordinate! Thanks for that Christoph!

Steve, the issue you might be having with the script is the order of the guides. I'm not sure if they are listed in the array from which was drawn first or which has a higher or lower value. You will need to add some code to make sure the values align with the script: top is the smallest horizontal value, etc. Use Math.min() and Math.max() for that.

Edit. opps, Christoph did add the Math.min().

JJMack
Community Expert
Community Expert
May 2, 2016

To me it sounds like you could create your action where you set the three guides  an insert a stop message so you can stop the action so you can manually drag our the fourth guide. Once you do you click the Play button and the action continues.  The next step runs a crop script that you write.  The script retrieves the four guides location set a selection for the rectangle formed then does an image crop then ends with a deselect.

JJMack