Image callouts

Volume 9, Issue 58; 10 Jun 2006; last modified 08 Oct 2010

A couple of simple tools designed to make the DocBook imageobjectco tag more usable.

In designing DocBook markup, we've always tried to stay within the capabilities of common, or at least known, processors. No matter how sophisticated and semantically rich a markup design is, if there aren't any tools that can actually process it in a meaningful way, it's not very practical.

Arguably, we were persuaded (back in mid-nineties) to introduce graphic callouts before their time. (Or maybe one of the important users at the time had a processor that could use them, I don't actually recall.) It's always bothered me that they were so hard to use.

For those of you not familiar with this particular corner of DocBook, graphic callout markup looks like this:

<mediaobject>
  <imageobjectco>
    <areaspec>
      <area xml:id="p1" coords="240,9049 497,8786"   linkends="c1"/>
      <area xml:id="p2" coords="2905,1360 3162,1098" linkends="c2"/>
      <area xml:id="p3" coords="8796,1491 9052,1229" linkends="c3"/>
    </areaspec>
    <imageobject>
      <imagedata fileref="duckl-co.png"/>
    </imageobject>
  </imageobjectco>
</mediaobject>

(There's a corresponding element for callouts in a program listing or other verbatim text, but it's well supported and fairly easy to understand.)

The idea is that those coordinates, expressed in somewhat idiosyncratic units borrowed from CALS, identify a region of the graphic where a “callout” occurs, that is, a link to some description or other content related to that region of the graphic. Here's a silly example:

In a browser context, the client side image map needed to make the links active is generated automatically. So once you have the graphic and the markup, it works reasonably well.

There are two big problems: first, you have to generate CALS coordinates that exactly correspond to the marks in the graphic. Second, you have to actually add the callout marks to the graphic. As far as I can tell, there's no way (in CSS, for example) to persuade the renderer to add the marks as overlaysThis would require support for relative positioning on top of a relatively positioned graphic. If it's possible, I'd love to be proved wrong..

The CALS coordinates express the region using percentages of the graphic size with an origin in the lower left corner. You only have to work your way from pixels to CALS units with a calculator once to convince yourself that you never want to do it again.

So I wrote a tool to do that part. Presented with a graphic consisting only of rectangles on a plain background, it will find the rectangles and calculate the CALS coordinates.

Using layers in an editor like the GIMP makes it pretty easy to generate that graphic.

  1. Open the original graphic.

  2. Add a new layer with a white background. Set the opacity to about 40%.

  3. Select the pencil tool. Set the foreground color to black. Choose an appropriate square brush. Add rectangles where you'd like the callouts to appear.

  4. Raise the opacity of the layer to 100% and save the image as a PNG (using a different name, of course, and exporting it so that only the visible layer is in the saved image).

Now run areasearch on that graphic. This will print the relevant areas:

$ areasearch images/duckr-callouts.png 
Loading images/duckr-callouts.png...
Searching for background color...
Searching for rectangles...
New rectangle at 276, 16 (10 x 10)
New rectangle at 156, 153 (10 x 10)
New rectangle at 18, 186 (10 x 10)
New rectangle at 164, 247 (10 x 10)
New rectangle at 179, 264 (10 x 10)
<area xml:id="" linkends="" units="calspair" coords="9200,9455 9500,9149"/>
<area xml:id="" linkends="" units="calspair" coords="5200,4795 5500,4489"/>
<area xml:id="" linkends="" units="calspair" coords="600,3673 900,3367"/>
<area xml:id="" linkends="" units="calspair" coords="5466,1598 5766,1292"/>
<area xml:id="" linkends="" units="calspair" coords="5966,1020 6266,714"/>

The areas are displayed in top-to-bottom, left-to-right order. I actually want the last two areas to get the same number, so I edited the results a little bit when building my imageobjectco:

<mediaobject>
  <imageobjectco>
    <areaspec>
      <area xml:id="p4" linkends="c4" coords="9200,9455 9500,9149"/>
      <area xml:id="p5" linkends="c5" coords="5200,4795 5500,4489"/>
      <area xml:id="p6" linkends="c6" coords="600,3673 900,3367"/>
      <areaset xml:id="p7" linkends="c7">
	<area coords="5466,1598 5766,1292"/>
	<area coords="5966,1020 6266,714"/>
      </areaset>
    </areaspec>
    <imageobject>
      <imagedata fileref="images/duckr-co.png"/>
    </imageobject>
  </imageobjectco>
</mediaobject>

Now I can go back and add the actual callout numbers to the graphic and I'll be ready to go.

But wait. I already know where I want the callouts to go, why am I doing this by hand? The areas in the DocBook document identify the numbers and their locations, all I need is a tool to combine them.

In the DocBook document, the graphic identified in the fileref attribute is the image that will be displayed. If we want a tool to do the work, we need to tell that tool how to find the original, pristine image. I could have done this with a naming convention or by relative location, but I decided to use a processing instruction. Adding <?base-image figures/duckr.png?> to the imageobject gives areaoverlay enough information to do the work.

The result is just what you'd expect.

One interesting feature of the CALS units is that, because they're percentages, the same callout markup can be used to put callouts on both a low resolution image for screen presentation and a high resolution image for print presentation.

These tools make imageobjectco much easier to use, maybe even practical. At last.

Comments

I'd say it is possible, A List Apart has an example.

The example uses loads of javascript to show info when hovering, but just putting the "action points" (dt:s) on the image is done with plain css (the "showing info" part is possible to do in plain css as well, but it won't work in msie, which doesn't support the :hover selector).

—Posted by Rasmus Kaj on 11 Jun 2006 @ 10:50 UTC #

I'm wondering how a mouse-free user makes use of these Norm? Is there any keyboard access at all?

—Posted by Dave Pawson on 12 Jun 2006 @ 11:35 UTC #

Good point, Dave. I haven't investigated keyboard shortcuts yet. There is a provision for alternate text for each callout, though I've failed to use it in these examples :-( I'll try to fix that.

—Posted by Norman Walsh on 12 Jun 2006 @ 02:52 UTC #

Excellent idea ! Unfortunately people like me are not very familiar to process perl scripts from java xslt engine through processing instructions. It would be great to put the same functionality in java into xalan and saxon extensions. Both of them support extensibility. Moreover this would make this process portable on every java supporting platform.

—Posted by Bertrand GILLIS on 28 Jun 2006 @ 09:37 UTC #