Image Names
Script for Adobe InDesign
Label placed graphics with their file names.
- Select layers for images and text frames
- Images and text can be on same layer
- Run again to replace text labels
How-to Video
Before using the script
The script requires a document is created beforehand. The document is a layout of placed graphics and empty text frames arranged as desired, together on one layer, or each on separate layers. Ensure unrelated design elements are on other layers, otherwise the script will confuse which text frame belongs with which image. The order of layers is not important. Which layer is the images, and which is the text, are selected in the script interface.
Text does not have to be below each image. It can be above or to one side. The only requirement is the image and text frames form two consistently spaced grids of an equal number of rectangles and text frames. Text frames should have a paragraph style assigned to aid formatting. Also consider setting text frames to auto-size height, to avoid overset text.
How to use the script
The interface is two sections, Layers and Options. Set options as desired and click OK to begin.
The script looks at all placed graphics on the selected layer, then all text frames on the selected layer. Both graphics and text frames are sorted by page, then by position starting from the top left, across to the right, then the next row down, etc. Then the file name of each placed graphic is inserted into the nearby text frame.
If later any images are updated to a different file, run the script again. This does not add additional text labels, rather replaces any that already exist.
Section 1: Layers
Images — select the layer of placed graphics (images).
Text — select the layer of text frames.
Images and text can be on the same layer. If so, select the same layer for both.
Section 2: Options
Name without extension — enable to omit the file extension from the text label for each placed graphic.
Source code
(download button below)
/*
Image Names
Copyright 2023 William Campbell
All Rights Reserved
https://www.marspremedia.com/contact
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
(function () {
var title = "Image Names";
if (!/indesign/i.test(app.name)) {
alert("Script for InDesign", title, false);
return;
}
// Script variables.
var count;
var doc;
var doneMessage;
var error;
var layerNames;
var progress;
// Reusable UI variables.
var g; // group
var gc1; // group (column)
var gc2; // group (column)
var p; // panel
var w; // window
// Permanent UI variables.
var btnCancel;
var btnOk;
var cbWoExtension;
var listLayerRect;
var listLayerText;
// SETUP
try {
// Script requires open document.
if (!app.documents.length) {
alert("Open a document", title, false);
return;
}
doc = app.activeDocument;
// Make list of layers.
layerNames = doc.layers.everyItem().name;
} catch (e) {
// Setup failed.
alert("An error has occurred.\nLine " + e.line + ": " + e.message, title, true);
return;
}
// CREATE PROGRESS WINDOW
progress = new Window("palette", "Progress", undefined, {
"closeButton": false
});
progress.t = progress.add("statictext");
progress.t.preferredSize.width = 450;
progress.b = progress.add("progressbar");
progress.b.preferredSize.width = 450;
progress.display = function (message) {
message && (this.t.text = message);
this.show();
this.update();
};
progress.increment = function () {
this.b.value++;
};
progress.set = function (steps) {
this.b.value = 0;
this.b.minvalue = 0;
this.b.maxvalue = steps;
};
// CREATE USER INTERFACE
w = new Window("dialog", title);
w.alignChildren = "fill";
// Panel 'Layers'
p = w.add("panel", undefined, "Layers");
p.orientation = "column";
p.alignChildren = "left";
p.margins = [18, 24, 18, 18];
// Group of 2 columns.
g = p.add("group");
// Groups, columns 1 and 2.
gc1 = g.add("group");
gc1.orientation = "column";
gc1.alignChildren = "left";
gc2 = g.add("group");
gc2.orientation = "column";
gc2.alignChildren = "left";
// Rows.
gc1.add("statictext", undefined, "Images:").preferredSize.height = 23;
listLayerRect = gc2.add("dropdownlist", undefined, layerNames);
listLayerRect.preferredSize = [150, 23];
listLayerRect.selection = 0;
gc1.add("statictext", undefined, "Text:").preferredSize.height = 23;
listLayerText = gc2.add("dropdownlist", undefined, layerNames);
listLayerText.preferredSize = [150, 23];
listLayerText.selection = 0;
// Panel 'Options'
p = w.add("panel", undefined, "Options");
p.alignChildren = "left";
p.margins = [24, 24, 24, 18];
cbWoExtension = p.add("checkbox", undefined, "Name without extension");
// Action Buttons
g = w.add("group");
g.alignment = "center";
btnOk = g.add("button", undefined, "OK");
btnCancel = g.add("button", undefined, "Cancel");
// Panel Copyright
p = w.add("panel");
p.add("statictext", undefined, "Copyright 2023 William Campbell");
// UI ELEMENT EVENT HANDLERS
btnOk.onClick = function () {
w.close(1);
};
btnCancel.onClick = function () {
w.close(0);
};
// DISPLAY THE DIALOG
if (w.show() == 1) {
doneMessage = "";
try {
app.doScript(process, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, title);
doneMessage = count + " placed graphics labeled";
} catch (e) {
error = error || e;
doneMessage = "An error has occurred.\nLine " + error.line + ": " + error.message;
}
progress.close();
doneMessage && alert(doneMessage, title, error);
}
//====================================================================
// END PROGRAM EXECUTION, BEGIN FUNCTIONS
//====================================================================
function process() {
var graphic;
var i;
var layerRect;
var layerText;
var link;
var rectangles = [];
var textFrames = [];
// During script, make measurement unit points.
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
progress.display("Initializing...");
try {
layerRect = doc.layers[listLayerRect.selection.index];
layerText = doc.layers[listLayerText.selection.index];
// Get rectangles.
for (i = 0; i < layerRect.rectangles.length; i++) {
if (layerRect.rectangles[i].parentPage) {
rectangles.push(layerRect.rectangles[i]);
}
}
// Get text frames.
for (i = 0; i < layerText.textFrames.length; i++) {
if (layerText.textFrames[i].parentPage) {
textFrames.push(layerText.textFrames[i]);
}
}
// Sort frames.
rectangles.sort(sortFrames);
textFrames.sort(sortFrames);
// Set text frames to image names.
count = 0;
progress.set(layerRect.rectangles.length);
for (i = 0; i < rectangles.length; i++) {
progress.increment();
graphic = rectangles[i].allGraphics[0];
try {
link = graphic.itemLink; // Throws error if graphic inline and overset.
if (link) {
// Linked graphic.
progress.display(link.name);
if (i < textFrames.length) {
// Update text.
if (cbWoExtension.value) {
// Remove extension.
textFrames[i].contents = link.name.replace(/\.[^\.]*$/, "");
} else {
// Entire name including extension.
textFrames[i].contents = link.name;
}
}
count++;
}
} catch (_) {
// Probably graphic inline and overset.
// Ignore.
}
}
} catch (e) {
error = e;
throw e;
}
}
function sortFrames(a, b) {
var ap;
var ax;
var ay;
var bp;
var bx;
var by;
var diff;
// Get parent pages.
ap = a.parentPage.documentOffset;
bp = b.parentPage.documentOffset;
if (ap == bp) {
// Same page.
// Get x and y positions.
ax = a.geometricBounds[1];
ay = a.geometricBounds[0];
bx = b.geometricBounds[1];
by = b.geometricBounds[0];
// Calc difference in Y position.
diff = ay - by;
if (Math.abs(diff) < 18) {
// Consider Y equal if within 18 points.
// Sort across.
return ax - bx;
}
// Otherwise sort top to bottom.
return diff;
}
// Otherwise sort by page.
return ap - bp;
}
})();
Image Names
For help installing scripts, see How to Install and Use Scripts in Adobe Creative Cloud Applications.
IMPORTANT: scripts are developed for the latest Adobe Creative Cloud applications. Many scripts work in CC 2018 and later, even some as far back as CS6, but may not perform as expected, or run at all, when used in versions prior to 2018. Photoshop features Select Subject and Preserve Details 2.0 definitely fail prior to CC 2018 (version 19) as the features do not exist in earlier versions. For best results use the latest versions of Adobe Creative Cloud applications.
IMPORTANT: by downloading any of the scripts on this page you agree that the software is provided without any warranty, express or implied. USE AT YOUR OWN RISK. Always make backups of important data.
IMPORTANT: fees paid for software products are the purchase of a non-exclusive license to use the software product and do not grant the purchaser any degree of ownership of the software code. Author of the intellectual property and copyright holder William Campbell retains 100% ownership of all code used in all software products regardless of the inspiration for the software product design or functionality.