Skip to main content
Inspiring
April 13, 2022
Answered

Automated Image Cropping

  • April 13, 2022
  • 8 replies
  • 6708 views

I flow a lot of source images into InDesign, but most of the image frames are originally in square dimensions (like 3" x 3" or 12" x 12"). This is the case even if the image inside the frame is 3" x 12" (example image attached).

 

The frame I need images to fit into (rectangle frame tool) has a measurement of 1.5" x 2.85" and the images need to scale proportionally. They fit properly when I place them, but the original empty space from the images is still showing. My only fix for the last few years has been to manually crop out the excess space in each image that needs it. I was wondering if (hoping!) there's a way to automatically crop out this extra space when the images are originally placed.

This topic has been closed for replies.
Correct answer rob day

Hi @Red-Temujin , just to follow up on the Photoshop trim command, not sure if this works for you, but the script below will open the document links in Photoshop, and trim away the white pixels. My example opens all of the links, which you might not want, but it could also specify the links on a targeted layer, or the single link as you place:

 

 

Edited Code:

 

 


//#targetengine "session"; 
//opens document links in Photoshop and trims
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var lnks = app.documents[0].links;
var pad = 4;
var img, fr, x;
for (var i = 0; i < lnks.length; i++){
    trimLink(lnks[i].filePath);
    while (lnks[i].status != LinkStatus.NORMAL) {lnks[i].update()}
    img = lnks[i].parent
    fr = img.parent
    x = fr.geometricBounds[3]-img.geometricBounds[3]
    img.move([0,0], [x,0]); 
    img.fit(FitOptions.FRAME_TO_CONTENT);
    fr.textWrapPreferences.properties = {textWrapMode:TextWrapModes.BOUNDING_BOX_TEXT_WRAP, textWrapOffset:[0,pad,0,pad] }
};   


/**
* A function to run in Photoshop 
* @ param file path 
* return file path 
*/
function trimLink(pa){
    var bt = new BridgeTalk();  
    bt.target = "photoshop";  
    bt.body = psScript.toString() + "\rpsScript('"+pa+"');";
    bt.onResult = function(resObj) { }  
    bt.onError = function( inBT ) { alert(inBT.body); };  
    bt.send(8);  

    //opens the link, trims white pixels and saves
    function psScript(pa) {  
        app.bringToFront();
        open(File(pa));
        var d = app.activeDocument;
        d.trim(TrimType.TOPLEFT);
        d.save();
        d.close();
    }  
};

 

 

 

 

 

Run on your sample files:

 

 

 

 

8 replies

Braniac
April 25, 2022

Hi Rob,

did some tests with your TrimLink.jsx script.

I see three things that could be or actually are an issue:

 

[ 1 ] The frame fitting options should be reset before the image is trimmed and the link is updated.

Had some tests without resetting the frame fitting options.

 

Before the script run where I selected the image at the top:

 

The result:

After adding some code that also addresses two other issues I had this correct result:

 

[ 2 ] textWrapOffset does NOT WORK when defined inside properties object.

At least with InDesign 16.4 on my Windows machine. So I added the code for textWrapOffset outside of the property properties.


[ 3 ] app.displayDialogs = DialogModes.NO ; added to PhotoShop script code.

My color management settings in PhotoShop would detect a missing or not matching color profile and will ask what to do if the image is opened in PhotoShop. So I reset the app.displayDialogs to show no dialogs.

 

Changed code for TrimLink.jsx script below where I added a global undo ( not for the trimming of the image in PhotoShop! ) and did a bit restructuring. And I added your pad for the text wrap only on the left of the frame:

 

/**
* @@@BUILDINFO@@@ TrimLink-EDITED-BY-UL.jsx !Version! Sun Apr 24 2022 17:48:15 GMT+0200
*/

/*
	Script by Rob Day.
	
	EDITED BY UWE LAUBENDER
	
	ISSUES RESOLVED:
	[ 1 ] The frame fitting options should be reset before the image is trimmed and the link is updated.
	[ 2 ] textWrapOffset does NOT WORK when defined inside properties object.
	[ 3 ] app.displayDialogs = DialogModes.NO ; added to PhotoShop script.
	
*/

( function()
{

app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;

app.doScript
(
	trimImageOfSelectedImage, 
	ScriptLanguage.JAVASCRIPT, 
	[],
	UndoModes.ENTIRE_SCRIPT, 
	"Trim Image of Selected Image | SCRIPT"
);

function trimImageOfSelectedImage()
{

if( app.selection.length != 1 ){ return };
if( app.selection[0].constructor.name != "Image" )
{
	alert("Please Direct Select an Image and Try Again.") ;
	return;
};

var doc = app.activeDocument ;
var prefs = doc.viewPreferences.properties;
var imagePrefs = app.imagePreferences.properties;

app.imagePreferences.preserveBounds = false

doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS ;
doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS ;

var s=app.activeDocument.selection[0];  
var leftPad = 4;
var lnk, img, fr, x;


// [ 220424-1 ] EDIT UWE LAUBENDER
//RESET FRAME FITTING OPTIONS
s.parent.frameFittingOptions.properties =
{
	autoFit : false ,
	fittingOnEmptyFrame : EmptyFrameFittingOptions.NONE ,
	leftCrop : 0 ,
	rightCrop : 0 ,
	topCrop : 0 ,
	bottomCrop : 0
};

lnk = s.itemLink;
trimLink(lnk.filePath);

while (lnk.status != LinkStatus.NORMAL) { lnk.update() };
img = lnk.parent ;
fr = img.parent ;

x = fr.geometricBounds[3]-img.geometricBounds[3] ;
img.move([0,0], [x,0]); 
img.fit(FitOptions.FRAME_TO_CONTENT);

// [ 220424-1 ] ANNOTION UWE LAUBENDER
// textWrapOffset DOES NOT WORK:
//  fr.textWrapPreferences.properties = {textWrapMode:TextWrapModes.BOUNDING_BOX_TEXT_WRAP, textWrapOffset:[0,pad,0,pad] };

fr.textWrapPreferences.properties =
{
	applyToMasterPageOnly : false ,
	inverse : false ,
	textWrapMode : TextWrapModes.BOUNDING_BOX_TEXT_WRAP ,
};

fr.textWrapPreferences.textWrapOffset = 
[
	0, 
	leftPad, 
	0, 
	0
];

doc.viewPreferences.properties = prefs ;
 
/**
* A function to run in Photoshop 
* @ param file path 
* return file path 
*/
function trimLink(pa)
{
    var bt = new BridgeTalk();  
    bt.target = "photoshop";  
    bt.body = psScript.toString() + "\rpsScript('"+pa+"');";
    bt.onResult = function(resObj) {}  ;
    bt.onError = function( inBT ) { alert(inBT.body); };  
    bt.send(8);  

	//opens the link, trims white pixels and saves
	function psScript(pa)
	{  
		
		// [ 220424-1 ] EDIT UWE LAUBENDER
		var startWithDialogs = app.displayDialogs ;
		app.displayDialogs = DialogModes.NO ;
		
		app.bringToFront();
		open(File(pa));
		var d = app.activeDocument;
		d.trim(TrimType.TOPLEFT);
		d.save();
		d.close();
		
		// [ 220424-1 ] EDIT UWE LAUBENDER
		app.displayDialogs = startWithDialogs;
	};
};

};

}() )

 

Regards,
Uwe Laubender

( ACP )

rob day
Braniac
April 25, 2022

textWrapOffset does NOT WORK when defined inside properties object.

At least with InDesign 16.4 on my Windows machine. So I added the code for textWrapOffset outside of the property properties.

 

Thanks Uwe, I wonder if the textWrapOffset problem is a scripting bug or something specific to the document we are testing. In general it seems to be working for me with 16.4 on Mojave:

 

app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var s=app.activeDocument.selection[0];  
s.textWrapPreferences.properties = {textWrapMode:TextWrapModes.BOUNDING_BOX_TEXT_WRAP, textWrapOffset:[0,50,0,50] };

 

 

 

Also I wonder if a BridgeTalk script that adjusts an existing layout is over complicating things for @Red-Temujin , maybe all that’s needed is a Photoshop action or script to batch the Trim before the layout is constructed:

 

//Photoshop script to batch trimming
var startWithDialogs = app.displayDialogs ;
var f = Folder.selectDialog("Select the folder containing the images"); 
if(f != null){ 
    fa = f.getFiles(/\.(jpg|jpeg|png|tif|psd)$/i);
}
for (var i = 0; i < fa.length; i++){
    open(File(fa[i]));
    var d = app.activeDocument;
	d.trim(TrimType.TOPLEFT);
	d.save();
	d.close();
};   
app.displayDialogs = startWithDialogs;

 

 

Inspiring
April 25, 2022

It may be over-complicating things, @rob day, but I think it's the right option. The script needs to occur after layout, since my images are grabbed from urls at pagination, then placed into folders at that time. Also, somehow after running the script, closing InDesign and re-flowing with my diofferent parameters, it actually trims images with transparent backgrounds as well. I'm not quite sure how that happens, but I won't complain! You guys are more than welcome to keep perfecting the process, but I'm 100% satisfied with what you've made so far.

rob day
rob dayCorrect answer
Braniac
April 20, 2022

Hi @Red-Temujin , just to follow up on the Photoshop trim command, not sure if this works for you, but the script below will open the document links in Photoshop, and trim away the white pixels. My example opens all of the links, which you might not want, but it could also specify the links on a targeted layer, or the single link as you place:

 

 

Edited Code:

 

 


//#targetengine "session"; 
//opens document links in Photoshop and trims
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var lnks = app.documents[0].links;
var pad = 4;
var img, fr, x;
for (var i = 0; i < lnks.length; i++){
    trimLink(lnks[i].filePath);
    while (lnks[i].status != LinkStatus.NORMAL) {lnks[i].update()}
    img = lnks[i].parent
    fr = img.parent
    x = fr.geometricBounds[3]-img.geometricBounds[3]
    img.move([0,0], [x,0]); 
    img.fit(FitOptions.FRAME_TO_CONTENT);
    fr.textWrapPreferences.properties = {textWrapMode:TextWrapModes.BOUNDING_BOX_TEXT_WRAP, textWrapOffset:[0,pad,0,pad] }
};   


/**
* A function to run in Photoshop 
* @ param file path 
* return file path 
*/
function trimLink(pa){
    var bt = new BridgeTalk();  
    bt.target = "photoshop";  
    bt.body = psScript.toString() + "\rpsScript('"+pa+"');";
    bt.onResult = function(resObj) { }  
    bt.onError = function( inBT ) { alert(inBT.body); };  
    bt.send(8);  

    //opens the link, trims white pixels and saves
    function psScript(pa) {  
        app.bringToFront();
        open(File(pa));
        var d = app.activeDocument;
        d.trim(TrimType.TOPLEFT);
        d.save();
        d.close();
    }  
};

 

 

 

 

 

Run on your sample files:

 

 

 

 

Braniac
April 20, 2022

Hi Rob,

well, yes, that's the way to go, I think!

It's our OP's project so only Red-Temujin can know if the image material is good enough, e.g. all images have a background of white pixels only. Just to name one criterium.

 

Thanks for sharing the code.

 

Uwe Laubender

( ACP )

rob day
Braniac
April 20, 2022

If running the script on all of the document’s links doesn’t work (it looks like there will be links @Red-Temujin doesn‘t want to trim), here is a version that trims a selected image:

 

app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var s=app.activeDocument.selection[0];  
var pad = 4;
var lnk, img, fr, x;

if (s.constructor.name == "Image") {
	lnk = s.itemLink;
    trimLink(lnk.filePath);
    while (lnk.status != LinkStatus.NORMAL) {lnk.update()}
    img = lnk.parent
    fr = img.parent
    x = fr.geometricBounds[3]-img.geometricBounds[3]
    img.move([0,0], [x,0]); 
    img.fit(FitOptions.FRAME_TO_CONTENT);
    fr.textWrapPreferences.properties = {textWrapMode:TextWrapModes.BOUNDING_BOX_TEXT_WRAP, textWrapOffset:[0,pad,0,pad] }
} else {
    alert("Please Direct Select an Image and Try Again.")
}
 
/**
* A function to run in Photoshop 
* @ param file path 
* return file path 
*/
function trimLink(pa){
    var bt = new BridgeTalk();  
    bt.target = "photoshop";  
    bt.body = psScript.toString() + "\rpsScript('"+pa+"');";
    bt.onResult = function(resObj) {}  
    bt.onError = function( inBT ) { alert(inBT.body); };  
    bt.send(8);  

    //opens the link, trims white pixels and saves
    function psScript(pa) {  
        app.bringToFront();
        open(File(pa));
        var d = app.activeDocument;
        d.trim(TrimType.TOPLEFT);
        d.save();
        d.close();
    }  
}
Braniac
April 13, 2022

Thank you for providing the sample document with the image file.

Unfortunately the sample proofs that (mis)-using InDesign's 2021 new text wrap feature to crop that image is not good enough for the precision we need here:

 

 

That means we need the help of PhotoShop for pixel precision.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
April 14, 2022

Hopefully this sample works better.

Inspiring
April 14, 2022

Never mind. I tested the brush like you did the other image. I see what you mean. InDesign keeps a lower resolution image to work with, compared to the original. This makes the text wrap untenable....

 

But just thinking with my keyboard, do we really need the text wrap to work perfectly? All I need is the furthest left and right edges, or up and down edges.

Braniac
April 13, 2022

After re-reading your first message I think that maybe I'm missing something here.

 

Could you provide a sample document?

The document should contain one frame with the wrong position of the image inside its container frame.

Plus a second frame where you corrected the image.

 

Only the InDesign document is needed.

( Optional also include the original image file as well. )

 

In the meanwhile I did some tests with ExtendScript code that are looking promissing.

 

Thanks,
Uwe Laubender

( ACP )

Inspiring
April 13, 2022

I attached the InDesign document and the image file. I really appreciate your help with this!

Braniac
April 13, 2022

Hi Red-Temujin,

thank you for the second screenshot.

I know excatly what you mean.

But still I'm sceptical…

 

It should be doable with a script if the overall resolution and image quality is "good enough".

But you have to eyeball every result and correct a "wrongly" cropped image placed in a frame.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
April 13, 2022

Almost all images I deal with are hi-res (at least 1200 px x 1200 px). I understand some images may need the human touch, based on your picture above, but having the option to automate most of them would be a great help.

Braniac
April 13, 2022

Another word on this:
The better the resolution and the overall quality of the images you want to place, the better one could automate this with a script.. With poor image quality the results of a possible automation of this task will be mediocre to be not acceptable.

Here with your sample image its obvious that automation software needs a helping hand from a human being.

 

Regards,
Uwe Laubender

( ACP )

Braniac
April 13, 2022

More details below.

Even if I would like to script this ( which is technically doable) using the result path of the Text Wrap functionality of InDesign with Apply Text Wrap to Motif will not result in a perfect solution:

So with an image like that it's hard to impossible to automate this if you want the motif here, the rectangle with the rounded corners.

 

FWIW: What could yield a better result is a script that would use PhotoShop perhaps. But here we have also the issue to part the foreground motif from its background.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
April 13, 2022

To be more specific, I don't need all blank (white) space to be cut, only the space left and right or up and down before it comes in contact with the image. I attached an image with two examples to better explain.

Inspiring
April 13, 2022

The red lines of the two images are where the crops would be needed.

Braniac
April 13, 2022

" My only fix for the last few years has been to manually crop out the excess space in each image that needs it."

 

Well, do that in PhotoShop before placing the image in InDesign.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
April 13, 2022

A better background:

I place hundreds of images at a time directly from clients' libraries, which usually have the images in square dimensions. They're almost always different images, so first cropping in PhotoShop wouldn't help with the automation (unless there's a way to automate in PhotoShop and not in InDesign).

 

If what I'm asking for doesn't exist, I understand. I just wanted to ask the community to see if I could save myself from perfroming the most mundane task of the process.