AUTOMATE DOCUMENT IMAGE PLACEMENT

Previous posts demonstrate how we can use a text file to provide information for creating a grid of images with and without a caption. But what if you want to set up a document template that does not require a grid of images. Instead you would like to have placeholders for images placed strategically on pages. To automate image placement you may decide to use a script. For this some method will be needed to identify how placeholders will be matched to images to be placed. One way to do this is to use a naming convention. We will explore this option.

NAMING CONVENTION

A simple naming convention can be to use an incremented number as part of the name for the placeholder as well as the image. For instance, the placeholders could be named Image_01 through Image_99 and the file names could start with the incremented number, as in:

01_[Name of file.jpg]

The link, of course, is the number.

NAMING PLACEHOLDERS

For naming image placeholders you could select the items and use the following:

Name Selected Rectangles

tell application "Adobe InDesign CC 2019"
   set selList to selection
   if selList is not {} then
	set rectList to every item of selection where class of it is rectangle
	repeat with i from 1 to length of rectList
	   set theName to "image_" & (text -1 thru -2 of ("00" & i))
	   set name of item i of theList to theName
	end repeat
   end if
end tell

Notice the statement that creates the name using the repeat variable i.

set theName to "image_" & (text -1 thru -2 of ("00" & i))

This insures that numbers 1 through 9 are preceded with a zero, so that all numbers will have two digits. Be aware that the rectangles will be named in the order in which they were selected.

Placing Images

To place the images to the active spread, the following script could be used:

Place Images to Named

set theFolder to choose folder with prompt ("Select folder of images for placement")
set folderStr to theFolder as string
set fileNames to list folder theFolder
tell application "Adobe InDesign CC 2019"
   set thePage to active spread of layout window 1
   set rectList to every rectangle of thePage where name of it begins with "Image_"
   repeat with i from 1 to length of rectList
	set theName to name of item i of rectList
	set theNumber to (text -1 thru -2) of theName
	set fileName to my getFileName(theNumber, fileNames)
	set fileRef to (folderStr & fileName) as alias
	tell item i of rectList 
	   place fileRef
           fit given fill proportionally
	end tell
   end repeat
end tell
(*Uses repeat loop to find the item in the list that begins with the value 
of the variable theNumber*)
on getFileName(theNumber, fileNames)
   repeat with everyItem in fileNames
	if everyItem begins with theNumber then
	   exit repeat
	end if
   end repeat
   return contents of everyItem
end getFileName

The above will work only if all the rectangles are in the same spread. If more than one spread is involved, you will need to have some way to designate the spread as part of the naming convention or provide a way for the user to indicate the beginning number for the selected items.

MORE THAN ONE SPREAD

If the document is to have images on a number of spreads it may be best to place all of the image placeholders on a specific layer. For the purpose of the following example script, the layer is named “Images”. A problem becomes apparent when placing the images. A list of all of the images found on the layer does not return the items in the order in which they were created. But there is a fix. When page items are created, InDesign assigns them an id incrementally. To name the items in the order of creation, the script can get a list of item ids and then sort the list. This is used in the following:

Name All on Layer

set layerName to "Images"
tell application "Adobe InDesign CC 2019"
   set docRef to document 1
   tell docRef
	set layerRef to layer layerName
	set idList to id of rectangles of layerRef
	set sortedList to my sortList(idList)
	repeat with i from 1 to length of sortedList
	   set theName to "image_" & (text -1 thru -2 of ("00" & i))
	   set name of rectangle id (item i of sortedList) to theName
	end repeat
   end tell
end tell
sortedList
(*Sorts list of numbers in ascending order*)
on sortList(idList)
   set indexList to {}
   set sortedList to {}
   repeat (length of idList) times
	set lowItem to 0
	repeat with i from 1 to (length of idList)
	   if i is not in indexList then
		set thisItem to item i of idList
		if lowItem is 0 then
		   set lowItem to thisItem
		   set lowItemIndex to i
		else if thisItem comes before lowItem then
		   set lowItem to thisItem
		   set lowItemIndex to i
		end if
	   end if
	end repeat
	set end of sortedList to lowItem
	set end of indexList to lowItemIndex
   end repeat
   return sortedList
end sortList

To place the images into their respective placeholders, a script almost the same as the one above (Place Images to Named) can be used. In fact the script is so similar, you can copy it and paste it into a new script and make just a few changes. The changes are in the first three lines following the tell statement to InDesign.

Place Images on Layer

tell application "Adobe InDesign CC 2019"
   set docRef to document 1
   set layerRef to layer "Images" of docRef
   set rectList to every rectangle of layerRef where name of it begins with "Image_"
All the rest of the script is the same.

ADDING CAPTIONS

One option for adding captions would be to set up a document template with text frames to which Live Captions have been assigned (Object > Captions). The cool thing about Live Captions is that the assigned text frame is automatically populated using information found in the image file (metadata).

Those who have worked with InDesign’s Caption feature have discovered it can have some serious limitations. For this reason we will use the script that places the images. This will require that the images have metadata that can be used for the captions. The metadata will define the Document Title and Description in the image file. Metadata can be assigned while processing the file in Photoshop (File > File Info).

For styling the caption, the document will require a text object style named “Caption”. This style will use a paragraph style named “Caption” with Next Style checked. The Caption paragraph style will have a paragraph style named “Description” as its Next Style. To create a space between the image frame and the caption frame, set Inset Spacing for Top as desired (about 6 to 9 points).

Place Images With Caption_Layer

global captionDepth --depth of text frame for caption
set captionDepth to 60
set layerName to "Images"
set theFolder to choose folder with prompt ("Select folder of images for placement")
set folderStr to theFolder as string
set fileNames to list folder theFolder
set objectStyleName to "Caption"
tell application "Adobe InDesign CC 2019"
   set measurement unit of script preferences to points
   set layerRef to layer layerName of document 1
   set objectStyleRef to object style objectStyleName of document 1
   set rectList to every rectangle of layerRef where name of it begins with "Image_"
   repeat with i from 1 to length of rectList
	set theName to name of item i of rectList
	set theNumber to (text -1 thru -2) of theName
	set fileName to my getFileName(theNumber, fileNames)
	set fileRef to (folderStr & fileName) as alias
	tell item i of rectList
	   place fileRef
	   fit given fill proportionally
	   set imageRef to image 1
	   set gBounds to geometric bounds
	   set parentPage to parent page
	   set layerRef to item layer
	end tell
	set linkRef to item link of imageRef
	my addCaption(gBounds, linkRef, parentPage, layerRef, objectStyleRef)
   end repeat
end tell
(*Creates text frame for images that have metadata, sets text content,
assigns item layer and object style*)
on addCaption(gBounds, linkRef, parentPage, layerRef, objectStyleRef)
   tell application "Adobe InDesign CC 2019"
	copy gBounds to {y0, x0, y1, x1}
	set linkMeta to properties of link xmp of linkRef
	set textStr to document title of linkMeta & return
	set textStr to textStr & description of linkMeta
	if textStr is not "" then
	   tell parentPage
	      make text frame with properties {geometric bounds:{y1, x0, y1 + captionDepth, x1},¬
contents:textStr, item layer:layerRef, applied object style:objectStyleRef}
           end tell
        end if
   end tell
end addCaption
(*Uses repeat loop to find the item in the list that begins with the value
of the variable theNumber*)
on getFileName(theNumber, fileNames)
repeat with everyItem in fileNames
if everyItem begins with theNumber then
exit repeat
end if
end repeat
return contents of everyItem
end getFileName

If all goes well and the target document has a text frame Object Style with paragraph styles established, the placed images with their captions should look similar to the screencapture below.

…Our sample image with caption

ONWARD AND UPWARD

A lot of territory was covered in the scripts above. Walk through the code to make sure you understand how each script and its handlers accomplish the automation. To keep the code as concise as possible, the scripts make a lot of assumptions. To bullet-proof the scripts be sure to surround the top portion of the script with a try/on error trap to notify the user of a problem and exit the script gracefully.

Disclaimer:
Scripts provided are for demonstration and educational purposes. No representation is made as to their accuracy or completeness. Readers are advised to use the code at their own risk.