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

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

1.2K

Likes

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

Likes

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

Likes

Translate

Translate
Community Expert ,
Feb 27, 2020 Feb 27, 2020

Copy link to clipboard

Copied

Hi Peter,

 

There seems to be no direct property that provides the actual dimensions of the placed image, also reading the xmp would work only if you can make sure that the data is added into it correctly in the first place. I tried to put together a few lines of code that should do the trick, the idea is to clear any transformations applied to the image, use visual bounds property to calculate the height and width and then reverting the tranformation clear operation.

var image = app.documents[0].links[0].parent
image.clearTransformations()
var width = image.visibleBounds[3] - image.visibleBounds[1]
var height = image.visibleBounds[2] - image.visibleBounds[0]
app.documents[0].undo()

I have used just the first link of the document, you can add in the logic to loop ovver every link

 

-Manan

Likes

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
New Here ,
Feb 28, 2020 Feb 28, 2020

Copy link to clipboard

Copied

Hi Manan,

 

I tried this previously but did not get a return in pixels. I essentially need the same width x height numbers as the linked file. Is there a way to convert this?

Likes

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 ,
Feb 28, 2020 Feb 28, 2020

Copy link to clipboard

Copied

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 dimensions
$.writeln("Pixel Dimensions: " + getPixels(sel))
//returns Pixel Dimensions: 1920,1280

//the actual dimension in inches
var appi = sel.actualPpi
var aw = getPixels(sel)[0]/appi[0];
var ah = getPixels(sel)[1]/appi[1];
$.writeln("Actual Inch Dimensions: " + aw + " x " + ah)

/**
* returns the pixel dimensions of an image
* @param i an image 
*/
function getPixels(i){

    var r = i.effectivePpi;
    var w = i.geometricBounds[3] - i.geometricBounds[1];
    var h = i.geometricBounds[2] - i.geometricBounds[0];
    var hpd = Math.round(w * (r[0]));
    var vpd = Math.round(h * (r[1]));

    return [hpd, vpd];
}

 

 

 

 

 

 

 

 

 

 

Screen Shot 11.png

Likes

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
New Here ,
Feb 28, 2020 Feb 28, 2020

Copy link to clipboard

Copied

This worked perfectly, thank you so much!

Likes

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 ,
Feb 29, 2020 Feb 29, 2020

Copy link to clipboard

Copied

Hi Peter,

 

If the result is needed in pixels you can easily set the mesurementunits of scriptpreferences to the desired unit. See the modified script that will get the height and width in pixels

app.scriptPreferences.measurementUnit = MeasurementUnits.PIXELS
var image = app.documents[0].links[0].parent
image.clearTransformations()
var width = image.visibleBounds[3] - image.visibleBounds[1]
var height = image.visibleBounds[2] - image.visibleBounds[0]
app.documents[0].undo()

 

-Manan

Likes

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 ,
Feb 29, 2020 Feb 29, 2020

Copy link to clipboard

Copied

Hi Manan, I think Peter is looking for the image’s real or actual pixel dimensions.

 

InDesign’s Pixel ruler unit will measure an object in pixels, but InDesign defines the Pixel unit as a static 1/72". So here the Link panel shows the image’s actual pixel dimensions as 1920 x 1280, but InDesign’s transform panel measures the placed image as 345.6px x 230.4px:

 

Screen Shot.png

 

When the rulers are set as inches the image’s width is 4.8", and 4.8*72=345.6.

Likes

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 ,
Mar 01, 2020 Mar 01, 2020

Copy link to clipboard

Copied

Hi Rob,

 

Yes i also was working to get the actual dimension of the image which you highlighted in your screenshot. While i have used an algorithm similiar to the one you posted in one of my projects but the new algo that i wrote also seems to work correctly. See the video below, looking at your screenshot i am not sure why it is not working for you. Can you see anything that i am doing wrong?

https://www.dropbox.com/s/1x14m4yad17684d/screen%20recording%202020-03-02%20at%2010.57.38%20am.mov?d...

 

-Manan

Likes

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 ,
Mar 03, 2020 Mar 03, 2020

Copy link to clipboard

Copied

It's because the Effective resolution of your placed image is 72ppi, which happens to match InDesign’s 1/72" definition of a pixel dimension. I think if you try your script on a placed image that does not have an Actual Res of 72ppi, you will not get the image’s original pixel dimensions. The Effective resolution in my first example is 457ppi x 529ppi because of the scaling.

Likes

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 ,
Mar 03, 2020 Mar 03, 2020

Copy link to clipboard

Copied

When I trace your width and height on my image with an Actual Resolution of 400ppi, I get 345.6 x 230.4, and not the 1920 x 1280 pixel dimensions listed in Link Info

 

 

$.writeln("Dimensions: " + width + " x " + height) 
//Returns Dimensions: 345.6 x 230.4

 

 

 

Screen Shot 4.png

Likes

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
Engaged ,
Apr 27, 2021 Apr 27, 2021

Copy link to clipboard

Copied

 

 

 

// Select an image (NOT its frame) then run script.
var image = app.activeDocument.selection[0];
var hs = image.horizontalScale;
var vs = image.verticalScale;
var ppi = image.actualPpi;
var gb = image.geometricBounds;
var pixelsWide = Math.round((gb[3] - gb[1]) / (hs / 100) * ppi[0]);
var pixelsHigh = Math.round((gb[2] - gb[0]) / (vs / 100) * ppi[1]);
alert([pixelsWide, pixelsHigh]);

 

 

Some notes: flopped images will give negative results. Use Math.abs() on the results.

Also doesn't work for rotated images. For that, duplicate and clear rotation, take the measurment, then remove the duplicate.

 

I ran into this when wanting to add "pixel dimensions" to my script "Links Report." (https://www.marspremedia.com/software/indesign/links-report)

Not only rotated, but sheared throws it off, too, of course. I'll post here the function I came up with to handle both. For these cases I opted to make a new temp doc instead of duplicate the image in the current doc. I did this because I didn't want the dupe and clear showing in the undo menu of the target document. Here's my function...

 

function getPixelDimensions(image) {
    var gb; //  geometricBounds
    var h; //   height
    var hs; //  horizontalScale
    var ppi; // pixels per inch
    var td; //  temp document
    var tr; //  temp rectangle
    var tg; //  temp graphic
    var vs; //  verticalScale
    var w; //   width

    ppi = image.actualPpi;
    hs = image.horizontalScale;
    vs = image.verticalScale;
    if (image.rotationAngle !== 0 || image.shearAngle !== 0) {
        // Won't be correct if rotated or sheared.
        // Copy to a temp doc and clear rotation and shear.
        // Then measure, and dump the temp doc.
        td = app.documents.add();
        tr = image.parent.duplicate(td.pages[0]);
        tg = tr.graphics[0];
        tg.rotationAngle = 0;
        tg.shearAngle = 0;
        gb = tg.geometricBounds;
        td.close(SaveOptions.NO);
    } else {
        gb = image.geometricBounds;
    }
    w = Math.abs(Math.round((gb[3] - gb[1]) / (hs / 100) * ppi[0]));
    h = Math.abs(Math.round((gb[2] - gb[0]) / (vs / 100) * ppi[1]));
    return [w, h];
    // Returns array of two numbers, width and height.
    // Width = array[0], height = array[1]
}

 

William Campbell

Likes

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 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Hello.

Is there any way to put the unscaled dimensions of a link into a text box uner the image using these methods?

Likes

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
Engaged ,
Sep 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

With some work, sure. Use the functions posted to get the array of pixels wide x tall, then make a text box under the graphic and update the contents with the values. I have a script that puts the name of graphics on them. It could be modified to add this information instead. Download here. It's open source, fully editable.

http://www.marspremedia.com/software/indesign/label-graphic-links

In the function 'processGraphic' at some point early in the function call the other code to get the pixel dimensions. Store it in a variable, or variables. Then replace the line

textFrame.contents = name;

with (for example)

textFrame.contents = width + "px  X  " + height + " px";

That sort of thing, or something similar. Whatever you like. Then to put it below the graphic, instead of on top of it, modify the code that positions the text frame at the end of the function. There are two vars gb1 and gb2. 1 is the graphic bounds. 2 is the text frame bounds. Adjust the text frame bounds so its top is at the bottom of the graphic frame.

You can see a video of the original script in action here: https://youtu.be/eluuL8PX6I8

 

 

William Campbell

Likes

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 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Thankyou very much for this, it's a brilliant start.

I'm new to this and although i can see the function you mentioned and 'textFrame.contents' I have no idea how to call the pixel dimensions.

Seems i need to find a tutorial.

And as a matter of interest, on gb1, what do the 0,1,2 & 3 numbers do, are they y, x, height & width?

Appreciate the help so far.

Wx

Likes

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 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Newby again - this is Javascript right? So i know where to direct my Google search!

 

Likes

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
Engaged ,
Sep 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Yes and no. Officially it is "ExtendScript" which is Adobe's implementation of JavaScript specific to automating Adobe applications. Thing is, while it is JavaScript, it's OLD JS without many modern additions browsers have. Best advice for learning JS for Adobe apps is get an old book published before 2009. It helps to not waste time learning a bunch of features that came after that, but Adobe apps are clueless about.

 

William Campbell

Likes

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
Engaged ,
Sep 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Wasn't sure your level of ExtendScript and JavaScript experience. Sorry I didn't make it simpler. First, to answer your question about gb1 and 2... those are 'Geometric Bounds' (made short, just 'gb'). This is a common property used many places in Adobe apps. The property is a 4 element array. It gets a little confusing because not all the apps the array indexes are the same meaning (still trips me up as I code one app then another). But for InDesign anyway, the bounds array is [top, left, bottom, right]. And InDesign (unlike Illustrator) coordinates are from top left, going down to right. So having the bounds of something (a rectangle, image frame, text frame, etc.) this is saying where it's located on the page.

This actually sounds like a good idea for a new script, so I'll likely take my Label Graphic Links script, or possibly another one "Image Names" (also open source... http://www.marspremedia.com/software/indesign/image-names) and modify one or the other to achive the result you describe. Trouble is, I can't get to it for a least a week with the current load of custom scripts at the moment.

About a tutorial, I also have that on YouTube. Start here: https://youtu.be/XjmWX_qfLSU

I'll say more in the response to your next post.

 

William Campbell

Likes

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 07, 2022 Sep 07, 2022

Copy link to clipboard

Copied

Hi @wobblewoo , a page item doesn’t have a width and height property, but you can write a function that extracts it from the geometricBounds property. I use this:

 

//a selected page item
var s = app.activeDocument.selection[0]
//width and height as an array
var d = getWidthHeight(s);

alert(d[0] + "x" + d[1])




/**
* Get a page item’s width and height 
* @ param the page item 
* @ return an array [width, height] 
* 
*/
function getWidthHeight(pi){
    var wh = []
    var gb = pi.geometricBounds
    wh[0] = gb[3]-gb[1];
    wh[1] = gb[2]-gb[0]
    return wh
}

 

Screen Shot.png

Likes

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 08, 2022 Sep 08, 2022

Copy link to clipboard

Copied

Thankyou, ill have a look through this but it's the size of the link im trying to put in a box. For instance i have a link thats 12x12 and i place it in InDesign at 50%, my understanding is that your script will return 6x6 and i need it to be 12x12.

Likes

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 08, 2022 Sep 08, 2022

Copy link to clipboard

Copied

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 item 
* @ return an array [width, height] 
* 
*/
function getWidthHeight(pi){
    var wh = []
    var gb = pi.geometricBounds
    wh[0] = gb[3]-gb[1];
    wh[1] = gb[2]-gb[0]
    return wh
}

 

Screen Shot 5.png

Likes

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 15, 2022 Sep 15, 2022

Copy link to clipboard

Copied

Thanks both. Apologies for the delay, had a very busy few days.

The scaled image script works wonders for an image but i have Illustrator files which don't display acutal or effective PPI, so we cant find the scale. Can you get the imported scale some other way?

The attached AI file is 710 x 300mm and placed into ID at 18%.

The box displays (from your first script) as 127.8 x 54* and if i divide that by 0.18 i get, what i want,  710 x 300

I actually get a very precise 12 decimal place number 127.800145927429...

Likes

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 15, 2022 Sep 15, 2022

Copy link to clipboard

Copied

Hi @wobblewoo , I was assuming an image and getting the scale via the effective/actual res ratio, so we wouldn’t have to worry about transformation totals (could the link and its parent framed be scaled differently?). It could also work to set the transformationsAreTotals prefs to true and simply get the total scale. Try this:

 

 

var ot = app.transformPreferences.transformationsAreTotals
var doc = app.activeDocument
app.transformPreferences.transformationsAreTotals = true;
var s = doc.selection[0]
var d = getWidthHeight(s);
var sw = s.horizontalScale;
var sh = s.verticalScale;
var w = (100/sw) * d[0];
var h = (100/sh) * d[1];
app.transformPreferences.transformationsAreTotals = ot;


alert(w.toFixed (3) + " x " + h.toFixed (3))


/**
* Get a page item’s width and height 
* @ param the page item 
* @ return an array [width, height] 
* 
*/
function getWidthHeight(pi){
    var wh = []
    var gb = pi.geometricBounds
    wh[0] = gb[3]-gb[1];
    wh[1] = gb[2]-gb[0]
    return wh
}

 Screen Shot 23.png

Likes

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 16, 2022 Sep 16, 2022

Copy link to clipboard

Copied

Odd, when i run that script i get the image box dimensions, not what you have shown.

 

 

Likes

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 16, 2022 Sep 16, 2022

Copy link to clipboard

Copied

You have the container frame selected, select the placed AI file

Likes

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 16, 2022 Sep 16, 2022

Copy link to clipboard

Copied

Here’s a loop that adds a text frame with the dimensions in the upper left corner of the link—sets the dimensions in millimeters:

 

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 = d[0].toFixed (3) + " x " + d[1].toFixed (3)
    var tf = pp.textFrames.add({fillColor:"Paper", geometricBounds: [b[0]-5,b[1],b[0],b[3]], 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]]
}

Likes

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