Copy link to clipboard
Copied
I'm trying to write a script that, given an InDesign file, is able to compute the image dimensions of every image in the document. I need the original image dimensions, so the image link I believe. The problem is when I try to pull out tiff:ImageHeight and tiff:ImageWeight from the linkXmp, it never returns a value. Is there some easier way to do this without having to look into the image metadata?
Are you trying to get the actual (unscaled) pixel dimensions? An image has the effective ppi resolution property, so if the document units are set to inches, you can get the pixel dimensions. This gets the actual pixel (or inch) dimensions of a selected image:
var doc = app.activeDocument;
doc.viewPreferences.properties = {horizontalMeasurementUnits:MeasurementUnits.INCHES, verticalMeasurementUnits:MeasurementUnits.INCHES}
//a selected image
var sel = doc.selection[0];
//the actual pixel d
...
You can get the scale by dividing the Effective by Actual Res. Direct select an image and try this:
var s = app.activeDocument.selection[0]
//width and height as na array
var d = getWidthHeight(s);
if (s.constructor.name == "Image") {
var ep = s.effectivePpi
var ap = s.actualPpi
var w = (ep[0]/ap[0]) * d[0];
var h = (ep[1]/ap[1]) * d[1]
alert(w.toFixed (3) + " x " + h.toFixed (3))
} else {alert("Select an Image")}
/**
* Get a page item’s width and height
* @ param the page
...
Copy link to clipboard
Copied
That looks great on my initial test.
Can you help tell me where to change it to do the following:
Put the box bottom left, add the filename before it and mm (Millimeters after it)
Styling the text would be good too.
I'm new to this but worked out how to change the number of decimal places.
I can do my own research, but some direction would really help.
Thanks so very much so far.
Copy link to clipboard
Copied
I think ive just worked out how to add 'mm'.
At the end of line 13 i added:
+ " mm "
Now ive got to work out how to add the filename.
Copy link to clipboard
Copied
app.activeDocument.name
Copy link to clipboard
Copied
Brilliant, let me try....
Thats the document name, i need the link name.
Im learning loads here, thankyou
Copy link to clipboard
Copied
Assuming the selected element is stored in a var named "selection"...
selection.itemLink.name
But it's a good idea to confirm the selection is of type "Graphic". An image or text frame does not have a property "itemLink" so will throw an error. Before looking for a graphic name I do it this way...
doc = app.activeDocument;
selection = doc.selection[0];
if (selection) {
try {
if (selection instanceof Rectangle) {
link = selection.allGraphics[0].itemLink;
} else {
link = selection.itemLink;
}
} catch (_) {
// Ignore.
}
if (link) {
name = link.name;
// ... etc.
}
}
This also gets the graphic whether the container frame is selected or the graphic itself is selected. The test for instanceof Rectangle is where that is resolved.
Copy link to clipboard
Copied
I get an error when using on anything other than my test document:
Error Number:21
Error String: null is not an object
Points to line 14:
var tf = pp.textFrames.add({fillColor:"Paper", geometricBounds: [b[0]-5,b[1],b[0],b[3]], contents:dt});
Can it be made to only run on selected elements?
Copy link to clipboard
Copied
This is a pet peeve of mine. I don't care for all the properties loaded into a single line because you can't tell which property (setting it) is making it fail. I like to split it up like so, which I feel makes more readable code besides.
var tf = pp.textFrames.add();
tf.fillColor = "Paper";
tf.geometricBounds = [b[0]-5,b[1],b[0],b[3]];
tf.contents = dt;
Then when it errors it will be one of the three lines setting specific properties to the text frame object. Then you know which is the problem.
Now to go further (and answer another of your earlier questions), continue setting other properties of "tf" for the styling...
tf.paragraphs[0].appliedFont = app.fonts.itemByName("Arial\tRegular");
tf.paragraphs[0].fillColor = app.activeDocument.swatches.itemByName("Black");
tf.paragraphs[0].pointSize = 9; // points
Again if any of these fail, you'll get the line number that points to the exact property that doesn't work, either the property itself (object doesn't have that property) or the value (perhaps unacceptable value for the particular property).
Copy link to clipboard
Copied
It appears what you are trying to do is similar to some scripts on my website that are open source. The only difference is you are adding pixel dimensions. Have a look at the code for these scripts for ideas of how to handle a lot of what is needed. The script Label Graphic Links is nearly identical but only lists the link name, not dimensions.
http://www.marspremedia.com/software/indesign/label-graphic-links
http://www.marspremedia.com/software/indesign/image-names
http://www.marspremedia.com/software/indesign/links-rename-selected
Copy link to clipboard
Copied
That error reporting makes sense @willcampbell7
I now get the error:
Error String: name is undefined
Source: dt = name + " " + d[0].toFixed (0) + " x " + d[1].toFixed (0) + " mm "
I added the 'name' variable and spacing before the d[0]...
Only occurs when i dont select an image so not a dealbreaker mind you
Copy link to clipboard
Copied
Just like it says... "name is undefined".
I assume 'name' is a variable you've created. It needs to have a value assigned to it. What is it supposed to be? The link name? Without seeing at least part of the code, it's hard to diagnose the problem. If OK that it is undefined, at least set it to an empty string to start. var name = ""; when the var is declared. Then it gets set to another value later if an image is selected. That would eliminate the error message anyway.
Copy link to clipboard
Copied
Ive tried to piece together code here. I appreciate the support
doc = app.activeDocument;
selection = doc.selection[0];
if (selection) {
try {
if (selection instanceof Rectangle) {
link = selection.allGraphics[0].itemLink;
} else {
link = selection.itemLink;
}
} catch (_) {
// Ignore.
}
if (link) {
name = link.name;
// ... etc.
}
}
var ot = app.transformPreferences.transformationsAreTotals
app.scriptPreferences.measurementUnit = MeasurementUnits.MILLIMETERS;
app.transformPreferences.transformationsAreTotals = true;
var lnks = app.documents[0].links;
var p, d, b, pp, dt, tf;
for (var i = 0; i < lnks.length; i++){
p = lnks[i].parent;
d = getActualDim(p)
b = p.geometricBounds;
pp = p.parentPage;
dt = name + " " + d[0].toFixed (0) + " x " + d[1].toFixed (0) + " mm "
/**
* Lets try splitting apart tf function to find error
* Also add Styling _REMOVED DUE TO ERRORS
* var tf = pp.textFrames.add({fillColor:"Paper", geometricBounds: [b[0]-5,b[1],b[0],b[3]], contents:dt});
*/
var tf = pp.textFrames.add();
tf.fillColor = "Paper";
tf.geometricBounds = [b[0]-5,b[1],b[0],b[3]];
tf.contents = dt;
};
app.transformPreferences.transformationsAreTotals = ot;
app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
/**
* Gets a link’s actual dimensions
* @ param the placed object
* @ return the object’s actual width and height as an array
*/
function getActualDim(lnk){
var d = getWidthHeight(lnk);
var sw = lnk.horizontalScale;
var sh = lnk.verticalScale;
var w = (100/sw) * d[0];
var h = (100/sh) * d[1];
return [w,h]
}
/**
* Get a page item’s width and height
* @ param the page item
* @ return an array [width, height]
*
*/
function getWidthHeight(pi){
var gb = pi.geometricBounds
return [gb[3]-gb[1], gb[2]-gb[0]]
}
Copy link to clipboard
Copied
There are a number of problems here. Your code tests for a selection but then ignores it. The code appears to want to label every graphic in the document, not just the one selected. Is that the case? If so much needs to rework, which I'll do. But not until I know what your goal is -- all placed graphics? Or just the one selected?
Copy link to clipboard
Copied
Just the one selected would be ideal. Thats very kind. Not a direct selection, the picture box which seems to work at the moment
I could not get the font styling to work and i couldnt work out how to put the box below the image aligned to the left - but its all a learning curve right!
Copy link to clipboard
Copied
var doc = app.activeDocument;
var graphic;
var link;
var selection = doc.selection[0];
if (selection) {
try {
if (selection instanceof Rectangle) {
graphic = selection.allGraphics[0];
} else {
graphic = selection;
}
link = graphic.itemLink;
} catch (_) {
// Ignore.
}
if (link) {
var ot = app.transformPreferences.transformationsAreTotals;
var ro = doc.viewPreferences.rulerOrigin;
app.scriptPreferences.measurementUnit = MeasurementUnits.MILLIMETERS;
app.transformPreferences.transformationsAreTotals = true;
doc.viewPreferences.rulerOrigin = RulerOrigin.SPREAD_ORIGIN;
var d = getActualDim(graphic);
var b = graphic.parent.geometricBounds;
var dt = link.name + " " + d[0].toFixed(0) + " x " + d[1].toFixed(0) + " mm ";
var pp = graphic.parentPage || graphic.parent.parent;
var tf = pp.textFrames.add();
tf.contents = dt;
tf.paragraphs[0].alignToBaseline = false;
tf.paragraphs[0].justification = Justification.LEFT_ALIGN;
tf.textFramePreferences.autoSizingReferencePoint = AutoSizingReferenceEnum.TOP_LEFT_POINT;
tf.textFramePreferences.autoSizingType = AutoSizingTypeEnum.HEIGHT_AND_WIDTH;
tf.textFramePreferences.ignoreWrap = true;
tf.textFramePreferences.insetSpacing = 2;
tf.textFramePreferences.useNoLineBreaksForAutoSizing = true;
tf.textFramePreferences.verticalJustification = VerticalJustification.CENTER_ALIGN;
tf.textWrapPreferences.textWrapMode = TextWrapModes.NONE;
tf.fillColor = "Paper";
tf.paragraphs[0].appliedFont = app.fonts.itemByName("Arial\tRegular");
tf.paragraphs[0].fillColor = app.activeDocument.swatches.itemByName("Black");
tf.paragraphs[0].pointSize = 3.175; // 9 points in mm
// Move text frame to top-left corner of graphic.
// But not beyond page edge.
var x = Math.max(0, b[1]);
var y = Math.max(0, b[0]);
tf.move([x, y]);
app.transformPreferences.transformationsAreTotals = ot;
doc.viewPreferences.rulerOrigin = ro;
app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
}
}
/**
* Gets a link’s actual dimensions
* @ param the placed object
* @ return the object’s actual width and height as an array
*/
function getActualDim(lnk) {
var d = getWidthHeight(lnk);
var sw = lnk.horizontalScale;
var sh = lnk.verticalScale;
var w = (100 / sw) * d[0];
var h = (100 / sh) * d[1];
return [w, h];
}
/**
* Get a page item’s width and height
* @ param the page item
* @ return an array [width, height]
*
*/
function getWidthHeight(pi) {
var gb = pi.geometricBounds;
return [gb[3] - gb[1], gb[2] - gb[0]];
}
Copy link to clipboard
Copied
Another way to handle the styling might be to make or use an Object Style, which can include a Paragraph Style property. In this case I’ve added a function that will return an Object Style named "Label" if it exists, and if it doesn’t it will make one, which can then be applied to the new text frame’s properties.
main()
function main(){
var ot = app.transformPreferences.transformationsAreTotals
app.scriptPreferences.measurementUnit = MeasurementUnits.MILLIMETERS;
app.transformPreferences.transformationsAreTotals = true;
//an object style for the label text frame
var os = makeObjStyle(app.activeDocument, "Label")
var s = app.activeDocument.selection[0];
var lnk;
if (s!=undefined && s.constructor.name == "Image" || s.constructor.name == "PDF") {
lnk = s.itemLink
} else {
try {
lnk = s.allPageItems[0].itemLink;
}catch(e) {
alert("Please Select a Linked Item")
return
}
}
var p = lnk.parent.parent;
var d = getActualDim(p)
var b = p.geometricBounds;
var pp = p.parentPage;
var dt = lnk.name + "\t" + d[0].toFixed (3) + " x " + d[1].toFixed (3)+" mm"
//add the label to the bottom of the image
pp.textFrames.add({fillColor:"Paper", geometricBounds: [b[2],b[1],b[2]+5,b[3]], contents:dt, appliedObjectStyle:os});
app.transformPreferences.transformationsAreTotals = ot;
app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
}
/**
* Gets a link’s actual dimensions
* @ param the placed object
* @ return the object’s actual width and height as an array
*/
function getActualDim(lnk){
var d = getWidthHeight(lnk);
var sw = lnk.horizontalScale;
var sh = lnk.verticalScale;
var w = (100/sw) * d[0];
var h = (100/sh) * d[1];
return [w,h]
}
/**
* Get a page item’s width and height
* @ param the page item
* @ return an array [width, height]
*/
function getWidthHeight(pi){
var gb = pi.geometricBounds
return [gb[3]-gb[1], gb[2]-gb[0]]
}
/**
* Makes a new named ObjectStyle or returns an existing style
* @ param the document to add the style to
* @ param style name
* @ return the new object style
*/
function makeObjStyle(d, n){
if (d.objectStyles.itemByName(n).isValid) {
return d.objectStyles.itemByName(n);
} else {
return d.objectStyles.add({name:n});
}
}
Copy link to clipboard
Copied
Thats brilliant Rob with the Object style, however im back to the issue of it displaying the box size and not the link size. The code on Williams script works but i cannot style the box like your one.
On this example Williams output is on the top and correct and yours in on the bottom (ive not styled it here but know how to)
Copy link to clipboard
Copied
Combine the two. But I would do one thing different. If the object style doesn't exist, not only create it, give it some default formatting (auto-size, 2 mm inset, etc.; see the code added to the creation function). I didn't set a stroke but it seems to get one by default. But that could just be me. More could be added, like stroke weight and color. At this point fill is paper. That too could be other value.
var doc = app.activeDocument;
var graphic;
var link;
var selection = doc.selection[0];
if (selection) {
try {
if (selection instanceof Rectangle) {
graphic = selection.allGraphics[0];
} else {
graphic = selection;
}
link = graphic.itemLink;
} catch (_) {
// Ignore.
}
if (link) {
var ot = app.transformPreferences.transformationsAreTotals;
var ro = doc.viewPreferences.rulerOrigin;
app.scriptPreferences.measurementUnit = MeasurementUnits.MILLIMETERS;
app.transformPreferences.transformationsAreTotals = true;
doc.viewPreferences.rulerOrigin = RulerOrigin.SPREAD_ORIGIN;
// Get/make an object style for the label text frame.
var os = makeObjStyle(doc, "Label");
var d = getActualDim(graphic);
var b = graphic.parent.geometricBounds;
var dt = link.name + " " + d[0].toFixed(0) + " x " + d[1].toFixed(0) + " mm ";
var pp = graphic.parentPage || graphic.parent.parent;
var tf = pp.textFrames.add();
tf.appliedObjectStyle = os;
tf.contents = dt;
tf.paragraphs[0].alignToBaseline = false;
tf.paragraphs[0].justification = Justification.LEFT_ALIGN;
tf.paragraphs[0].appliedFont = app.fonts.itemByName("Arial\tRegular");
tf.paragraphs[0].fillColor = app.activeDocument.swatches.itemByName("Black");
tf.paragraphs[0].pointSize = 3.175; // 9 points in mm
// Move text frame to top-left corner of graphic.
// But not beyond page edge.
var x = Math.max(0, b[1]);
var y = Math.max(0, b[0]);
tf.move([x, y]);
app.transformPreferences.transformationsAreTotals = ot;
doc.viewPreferences.rulerOrigin = ro;
app.scriptPreferences.measurementUnit = AutoEnum.AUTO_VALUE;
}
}
/**
* Gets a link’s actual dimensions
* @ param the placed object
* @ return the object’s actual width and height as an array
*/
function getActualDim(lnk) {
var d = getWidthHeight(lnk);
var sw = lnk.horizontalScale;
var sh = lnk.verticalScale;
var w = (100 / sw) * d[0];
var h = (100 / sh) * d[1];
return [w, h];
}
/**
* Get a page item’s width and height
* @ param the page item
* @ return an array [width, height]
*
*/
function getWidthHeight(pi) {
var gb = pi.geometricBounds;
return [gb[3] - gb[1], gb[2] - gb[0]];
}
/**
* Makes a new named ObjectStyle or returns an existing style
* @ param the document to add the style to
* @ param style name
* @ return the new object style
*/
function makeObjStyle(d, n) {
var os;
if (d.objectStyles.itemByName(n).isValid) {
os = d.objectStyles.itemByName(n);
} else {
os = d.objectStyles.add();
os.name = n;
os.textFramePreferences.autoSizingReferencePoint = AutoSizingReferenceEnum.TOP_LEFT_POINT;
os.textFramePreferences.autoSizingType = AutoSizingTypeEnum.HEIGHT_AND_WIDTH;
os.textFramePreferences.ignoreWrap = true;
os.textFramePreferences.insetSpacing = 2; // mm
os.textFramePreferences.useNoLineBreaksForAutoSizing = true;
os.textFramePreferences.verticalJustification = VerticalJustification.CENTER_ALIGN;
os.textWrapPreferences.textWrapMode = TextWrapModes.NONE;
os.enableTextFrameGeneralOptions = true;
os.enableTextFrameAutoSizingOptions = true;
os.enableTextWrapAndOthers = true;
os.fillColor = "Paper";
}
return os;
}
Copy link to clipboard
Copied
For other text frame preferences to set in the object style (or directly to the frame) see the reference here:
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#TextFramePreference.html
Copy link to clipboard
Copied
Sorry, lines 21-24 should be:
var p = lnk.parent;
var d = getActualDim(p)
var b = p.parent.geometricBounds;
var pp = p.parentPage;
Where p is the linked object, and b is the bounds of the container, which are used to place the label text frame. b[2] is the bottom of the container, so it is set as the top of the new text frame, and then b[2]+5 is the bottom of the text frame.