Identify coordinates for a visual element in idml

2019-04-29 20:15发布

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?

标签: indesign idml
2条回答
狗以群分
2楼-- · 2019-04-29 20:24

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.

查看更多
看我几分像从前
3楼-- · 2019-04-29 20:41

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

查看更多
登录 后发表回答