Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identify coordinates for a visual element in idml

I need to process Indesign Idml files, generate an image, and overlay other elements over certain elements in html.

Given an Indesign Idml file (which is a package of zipped xml) and given a visual element in that file (via a tag in the xml). Is there a way to find at what coordinates on the image that visual element falls?

like image 490
George Mauer Avatar asked Sep 18 '12 16:09

George Mauer


2 Answers

The heirarchy of containers for an image in an IDML document is as follows:

Document [Contains] > Spread > PageItem > PlacedImage. Pages aren't used as containers, and PageItems are stored in spread coordinates, so we can forget about the Document and Page elements. if you can find a Placed Image in Spread coordinates, and rebase those coords so 0,0 is at the top left of your screen, you can position an image as it was in the InDesign document.

A page item (which contains an image) doesn't have geometric bounds in IDML. Its bounds are stored as an array of PathPointType objects within the PathGeometry tag, like this:

<Properties>
            <PathGeometry>
                <GeometryPathType PathOpen="false">
                    <PathPointArray>
                        <PathPointType Anchor="-32.04 -35.04" LeftDirection="-32.04 -35.04" RightDirection="-32.04 -35.04" />
                        <PathPointType Anchor="-32.04 35.04" LeftDirection="-32.04 35.04" RightDirection="-32.04 35.04" />
                        <PathPointType Anchor="32.04 35.04" LeftDirection="32.04 35.04" RightDirection="32.04 35.04" />
                        <PathPointType Anchor="32.04 -35.04" LeftDirection="32.04 -35.04" RightDirection="32.04 -35.04" />
                    </PathPointArray>
                </GeometryPathType>
            </PathGeometry>
        </Properties>

You can calculate the bounds yourself simply enough by getting the lowest/greatest point values, assuming the border around your page item is a rectangle. Then you need the item transform,

ItemTransform="1 0 0 1 509.27559055100005 -123.76377952749999"

...and you need to allow for where IDML thinks 0,0 is (which is the origin of the transform).

In the X axis, 0 will be the binding location (which is variable - in a single page document it's usually the left hand edge of the spread, but in a two page document it may be the center of the spread). This is where you will need pages. BindingLocation is expressed as an integer (0 for before the first page, 1 for between first and second, etc). You find the coords of this by adding up the ItemTransforms of the preceding pages.

In the Y axis, for reasons best known to Adobe, 0 is the vertical center of the spread (not either the top or bottom, as you might expect).

The IDML docs have coord examples: http://www.photoshopelementsmac.com/devnet/indesign/documentation.html including translating from one coord space to another.

Also, within a page item (which gives the geometric bounds), a placed image has its own set of graphic bounds, which can offset it further, as well as its own ItemTransform

So, to answer your question, you would need to unpack the IDML zip file, find the image in the XML, then do a sum something like:

// Pseudo-code:
// Calculate PageItem GeometricBounds First as noted above
X: (Spread.BindingLocation) + Spread.ItemTransform.tx + PageItem.itemTransform.tx + PageItem.GeometricBounds.Left + PlacedImage.ItemTransform.tx + PlacedImage.GraphicBounds.Left

Y: (Half Spread Height) + Spread.ItemTransform.ty + PageItem.itemTransform.ty + PageItem.GeometricBounds.Top+ PlacedImage.ItemTransform.ty + PlacedImage.GraphicBounds.Top

Oh, one more thing: all IDML coords are in points. You'll need to divide all values by 72 divided by the PPI of your screen if you want to get results in pixels.

like image 113
Jude Fisher Avatar answered Oct 24 '22 18:10

Jude Fisher


Each <PageItem> on a page uses the ItemTransform attribute to scale, rotate, shear, and transform itself relative to its containing element (technically the PageItem XML element doesn't exist but can be a Rectangle, Oval, etc. element).

Within the <PageItem>, its shape is determined by the <PathGeometry> element and its containing elements (the IDML reference describes this in detail with examples), also refer to JcFx's answer.

Heavily corrected answer based on IDML specification: Thanks to JcFx

like image 24
Josh Voigts Avatar answered Oct 24 '22 18:10

Josh Voigts