Fanning Software Consulting

Object Graphics Snapshots

QUESTION: If I want to take a snapshot of an IDL direct graphics window, it is unbelieveably easy. I just use your cgSnapshot program. But when I try to do something similar with an object graphics program, I often end up with garbage in my output file. It is as though the snapshot grabbed everything in the square frame of the window rectangle, not just the output I wrote into the window.

Here is an example, using your own XPlot program to create a TIFF file as output. The garbage in the window appears to be part of the Output pull-down menu.

Object graphics window snapshot contains garbage.
Object graphics window snapshot has extraneous material in output.

ANSWER: Wow! I hadn't noticed that before and the fact that no one has complained in the six years I've offered the program on my web page is testament, I suppose, to how popular and widely used my programs are. Sigh...

But you are correct. When the object graphics window is using hardware rendering (the default case), then taking a snapshot of the window, as in the code example below, will result in the "capture" acquiring everything currently in front of the window rectangle on the display. This can be menu fragments, the shadows or contents of other windows, and other extraneous things. Rick Towler, a reliable source on all things concerned with object graphics, claims that the computer's frame buffer is being captured. This appears to be the case on both Windows and UNIX platforms, although Macintosh computers appear to be exempt for some unknown reason (probably having to do with Steve Job's visionary approach to computer graphics).

Here is typical code for taking a snapshot of an object graphics window (either and IDLgrWindow object or a draw widget with the Graphics_Level keyword set to 2).

    objWindow -> GetProperty, IMAGE_DATA=snapshot 

In any case, it is a bother. What can you do about it?

There are two possible approaches. The easiest solution is to now allow the window to render itself in hardware. Rather, you can use the MESA OpenGL library shipped along with IDL and render the window in software. Software rendering is not subject to this read-through limitation. Simply set the Renderer keyword equal to 1 when you create an object graphics window, as in the code example below.

    objWindow = Obj_New('IDLgrWindow', XSIZE=400, YSIZE=350, RENDERER=1)


   drawID = Widget_Draw(tlb, XSIZE=400, YSIZE=350, RENDERER=1, GRAPHICS_LEVEL=2)
   Widget_Control, drawID, GET_VALUE=objWindow 

The second approach is to display the graphics hierarchy in an IDLgrBuffer object, and take a snapshot of the buffer object for your output image. The IDLgrBuffer object is always rendered in software, so it is not subject to this read-through limitation. Your code might look something like this.

     objWindow -> GetProperty, SCREEN_DIMENSIONS=dims
    buffer = Obj_New('IDLgrBuffer', DIMENSIONS=dims)     buffer -> Draw, theView
    buffer -> GetProperty, Image_Data=snapshot     Obj_Destroy, buffer 

Version of IDL used to prepare this article: IDL 7.0.3.

Web Coyote's Guide to IDL Programming