• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Having trouble extracting the pixel dimensions of an image link in Indesign

New Here ,
Feb 27, 2020 Feb 27, 2020

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?

TOPICS
How to , Scripting

Views

2.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Feb 28, 2020 Feb 28, 2020

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
...

Votes

Translate

Translate
Community Expert , Sep 08, 2022 Sep 08, 2022

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
...

Votes

Translate

Translate
Explorer ,
Sep 18, 2022 Sep 18, 2022

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. 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 18, 2022 Sep 18, 2022

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 18, 2022 Sep 18, 2022

Copy link to clipboard

Copied

app.activeDocument.name
William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 18, 2022 Sep 18, 2022

Copy link to clipboard

Copied

Brilliant, let me try....

Thats the document name, i need the link name.

Im learning loads here, thankyou

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 18, 2022 Sep 18, 2022

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.

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 18, 2022 Sep 18, 2022

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? 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 18, 2022 Sep 18, 2022

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).

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 18, 2022 Sep 18, 2022

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

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 20, 2022 Sep 20, 2022

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 20, 2022 Sep 20, 2022

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.

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 20, 2022 Sep 20, 2022

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]]
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 20, 2022 Sep 20, 2022

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?

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 20, 2022 Sep 20, 2022

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!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 20, 2022 Sep 20, 2022

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]];
}
William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 20, 2022 Sep 20, 2022

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});
    }
}


 

 

 

 

Screen Shot 1.png

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Sep 21, 2022 Sep 21, 2022

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)
Screen Shot 2022-09-21 at 18.28.00.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 21, 2022 Sep 21, 2022

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;
}

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Sep 21, 2022 Sep 21, 2022

Copy link to clipboard

Copied

LATEST

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

 

William Campbell

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 21, 2022 Sep 21, 2022

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.

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines