Category "Object graphics"


Sparklines are “simple, word-size graphics” intended to be be incorporated into a paragraph or table of words as equals. For example, the high was 55 degrees in Boulder today. But, this is put in context with a simple plot of the last 28 days highs Boulder weather 55. Now obviously, some of the features of a full-sized plot are are eliminated in this design. Estimating data points from the plot is impossible since no scale is given. But sparklines are not intended to replace full-sized plots, they are intended to augment and give context to a single number. This can be made even more informative with a band indicating the normal range of values, for example the same 28 days of high temperatures in Boulder Boulder weather with normal range a=band 55.

Right now, my routine (doc) only creates PNG images with a few options to control the colors and scales in the sparklines. I intend to add EPS output in the future. I also intend to develop a few routines for spark bar plots and dichotomous plots.

Sparklines will be a chapter in Tufte’s upcoming book, Beautiful Evidence. See this previous post for more information about the book.

IDL 6.2 added several new capabilities to the IDLgrImage class in the object graphics system. One of them is the ability to support large images using tiling. (Another is significantly faster rendering time in typical cases.)

mg_tilejp2 demo

The new tiling features allow portions of the image to be read from a data source as needed. For applications that zoom using data sources with an image pyramid, level of detail rendering is used. For example, if a thumbnail of the entire image is needed, only a low resolution image is requested from the data source and rendered by IDLgrImage.

The mechanics of how this works requires a bit of communication between the destination object (IDLgrWindow, IDLgrBuffer, IDLgrClipboard or IDLgrPrinter support it) and the IDLgrImage object using a few new methods (most notably, queryRequiredTiles for the destination objects and setTileDatafor IDLgrImage).

Running the demo

The demo program is a minimal tiling image viewer which supports scrolling (click and drag as well as with the arrow keys) and zooming (page up and page down). To test it out:

  1. First download the source code (mg_tilejp2.pro and mg_tilejp2_demo.pro).
  2. Change directories in IDL to a directory that you want to save the JPEG 2000 data file in.
  3. You need to run MG_TILEJP2_DEMO at least the first time you run the demo code in order for the JPEG2000 image to be created. After that, you can run MG_TILEJP2 directly.

How it works

The basic steps are pretty simple:

  1. set a few properties on the IDLgrImage object when you create it,
  2. query the destination object with the new queryRequiredTiles method for any new tile data to read, and
  3. set the tile data with the new setTileData method of IDLgrImage.

First, there a few new properties of IDLgrImage that you can now set. The TILING keyword must be set and TILED_IMAGE_DIMENSIONS must specify the full size of the image. The IDLgrImage initialization in the demo program looks like:

oimage = obj_new('IDLgrImage', name='image', order=1, $
                 /tiling, $
                 tile_show_boundaries=0, $
                 tile_level_mode=1, $ ; automatic mode for image pyramid
                 tiled_image_dimensions=imageDims, $
                 tile_dimensions=jp2TileDims)

The size of each tile is set through the TILE_DIMENSIONS keyword; the default value is [1024, 1024]. The keyword TILE_SHOW_BOUNDARIES can be set to show the boundaries of the tiles (handy when debugging). Finally, TILE_LEVEL_MODE specifies whether the application specificies the level through the TILE_CURRENT_LEVEL property (0) or if it done automatically (1). Since our demo program has a data source with an image pyramid, we can use automatic.

The guts of the tile handling is in the MG_TILEJP2_REFRESH routine that is called whenever the image needs to be redrawn (usually because the VEWPLANE_RECT of the view has been modified). Our refresh routinen is a typical example of filling in the tile data from a JPEG 2000 file:

pro mg_tilejp2_refresh, pstate
  compile_opt strictarr

  oimage = (*pstate).oview->getByName('model/image')
  reqTiles = (*pstate).owindow->queryRequiredTiles((*pstate).oview, $
                                                   oimage, $
                                                   count=nTiles)

  if (nTiles gt 0) then widget_control, /hourglass

  for t = 0L, nTiles - 1L do begin
    subrect = [reqTiles[t].x, reqTiles[t].y, $
               reqTiles[t].width, reqTiles[t].height]

    level = reqTiles[t].level
    scale = ishft(1, level) ; scale = 2^level
    subrect *= scale

    ojp2 = obj_new('IDLffJPEG2000', (*pstate).jp2filename, $
                   persistent=0)
    tileData = ojp2->getData(region=subrect, $
                             discard_levels=level, $
                             order=1)
    obj_destroy, ojp2
    oimage->setTileData, reqTiles[t], tileData, no_free=0
  endfor
  (*pstate).owindow->draw, (*pstate).oview
  widget_control, hourglass=0
end

Note how nicely the output of IDLgrWindow::queryRequiredTiles meshes with the keywords of IDLffJPEG2000::getData and the parameters of IDLgrImage::setTileData.

The rest is, as they say, details—that is, if you have a basic knowledge of object graphics and widget programming.

« newer posts