| Customize Help

Annotating the displayed image non-destructively



There are three ways to annotate an image on display:

  • Using MIL's overlay mechanism.

  • Using a 2D graphics list.

  • Using GDI annotations.

Annotating images using the overlay mechanism

For all types of displays, you can annotate the displayed image non-destructively using MIL's overlay mechanism. To make use of this functionality, do the following:

  1. Enable the overlay mechanism, using MdispControl() with M_OVERLAY set to M_ENABLE.

  2. Select an image buffer to the display, using MdispSelect().

    Since the overlay mechanism is enabled, this will not only display the selected image, but it will also associate a temporary overlay buffer with the display. This buffer is referred to as the display's overlay buffer. The overlay buffer can be used to annotate the underlying image with an effect called transparency, or keying. For more information, see Transparency (Keying).

  3. To access the display's overlay buffer, use MdispInquire() with M_OVERLAY_ID to determine the MIL identifier of the buffer.

  4. Annotate the display's overlay buffer as required. For example, to write text in the overlay buffer, you can use MgraText(). Note that since this temporary overlay buffer is a real image buffer, any function (except grabbing) can be used.

    You can also annotate the displayed image buffer or the overlay buffer with Windows GDI annotations. For information, see the Using GDI annotations subsection of this section.

The overlay buffer will have the same size as its associated image (not the size of the display). In addition, for windowed displays, it will have the same number of bands and depth as the desktop; for exclusive displays, it will have the same number of bands and depth as the selected display format.

Overlay buffer behavior

When an image is selected to a display that has an associated overlay buffer, and you select another image to that display, one of the following occurs:

  • If the new image has the same format and size as the image currently selected to that display, the current overlay buffer is not freed. Any annotations will, therefore, remain until you clear the overlay buffer, with MbufClear().

  • If the new image has a different format or size than the image currently selected to that display, the contents of the current overlay buffer are copied to a temporary buffer, the current overlay buffer is freed, another overlay buffer is created, and the annotations of the old overlay buffer are copied from the temporary buffer into the new overlay buffer. The new overlay buffer has the same size as the new image selected to the display.

    The identifier of the old overlay buffer is now obsolete. To inquire the identifier of this newly created overlay buffer, use MdispInquire() with the M_OVERLAY_ID inquire type.

Camera calibration and overlay considerations

MIL tries to keep the camera calibration information of the overlay buffer synchronized with the camera calibration information of the buffer selected to the display.

Note that camera calibration is not available with MIL-Lite.

MIL will copy the camera calibration information of the selected buffer to the overlay buffer at the following moments:

  • When the overlay buffer is allocated.

  • When a buffer is selected to the display.

  • When the camera calibration information of the selected buffer is modified.

Note that if the camera calibration information of the overlay buffer is modified with McalAssociate(), MbufClear(), or some other function, the camera calibration information of the selected buffer will not be updated accordingly. However, changing the camera calibration information of the selected buffer will re-copy the camera calibration information of the selected buffer to the overlay buffer, even if the camera calibration information of the overlay buffer was manually changed.

Transparency (Keying)

The display's overlay buffer annotates the image selected to the display using transparency. Transparency, also known as keying, is a mechanism that replaces pixels of an image that are of the specified transparency (keying) color with the underlying areas of another image. Using transparency, annotations made to the overlay buffer in a color other than the transparency color will annotate the image selected to the display.

When allocating a display (MdispAlloc()), the transparency color is automatically set to a default color, which is generally appropriate. Use MdispInquire() with M_TRANSPARENT_COLOR to determine the transparency color. If required, select another transparency color using MdispControl() with M_TRANSPARENT_COLOR.

If you are using an 8-bit display resolution (256 colors), set the transparency color to a value between 0 and 255. If you are using a non 8-bit display resolution (15-bit, 16-bit, 24-bit, or 32-bit color resolution), call the macro M_RGB888() and specify the RGB value. For example:

MdispControl(DisplayID, M_TRANSPARENT_COLOR, M_RGB888(20,32,24));

When the display's overlay buffer is created, it is cleared to the effective transparency color. If the transparency color is changed after the overlay buffer is created, the buffer will not be cleared to the new color.

Using a 2D graphics list

You can associate a 2D graphics list to the display. In this case, the vector-based graphics, contained within the 2D graphics list, will be used to annotate the display non-destructively. To perform such annotations, you must specify a valid 2D graphics list identifier, using MdispControl() with M_ASSOCIATED_GRAPHIC_LIST_ID. You must have previously allocated the 2D graphics list, using MgraAllocList(), and added one or more graphics to it, using MIL graphic functions (for example, MgraText() or using the M...Draw() functions). For more information, see the 2D graphics list section of Chapter 24: Generating graphics.

By default, modifications to the graphics within the list (added, deleted, or altered graphics) will be immediately reflected in the non-destructive annotation of the display. To change this behavior, use MdispControl() with M_UPDATE_GRAPHIC_LIST. To release the 2D graphics list from memory, use MgraFree(). If the associated 2D graphics list is freed, it is automatically disassociated from the display.

When you annotate the display non-destructively using a 2D graphics list, the zooming behavior of the display will be different than if you had annotated the display using the typical overlay mechanism. With the overlay mechanism, annotations are zoomed by resizing the overlay pixels, which can cause pixelation (loss of clarity), the loss of some annotations, or a change in line thickness. However, such effects do not occur when zooming a display that has 2D graphics list annotations (which are vector-based).

Notice how, in the example above, neither the size of the text nor the quality of the rectangle is affected by the zoom factor, for annotations with a 2D graphics list.

In addition, using a 2D graphics list, you can draw anywhere on the display. It does not have to be over the image buffer selected to the display.

Using GDI annotations

Besides using MIL functions (for example, MgraText()) to annotate your display, you can draw GDI annotations in the buffer selected to the display or in the display's overlay buffer.

To perform this technique:

  1. Allocate a device context (DC) for either the image buffer or the overlay buffer of the display using MbufControl() with M_DC_ALLOC. Windows GDI annotation functions require a DC to draw. You cannot allocate a DC for an image buffer that is not associated with a display. If you draw using the DC of the image buffer selected to the display, drawing will be destructive (that is, the data of the image buffer is actually changed).

  2. Inquire the identifier of the device context (DC) created in the previous step using MbufInquire() with the M_DC_HANDLE inquire type.

  3. Paint your annotations using Windows GDI annotation functions with the DC.

  4. Free the device context (DC), using MbufControl() with M_DC_FREE.

  5. Notify MIL that the display needs to be updated with the GDI annotations, using MbufControl() with M_MODIFIED.

When drawing GDI annotations using this technique, the images are drawn using the buffer's coordinates, and the annotations will follow the underlying image when the display is zoomed or panned. However, the size of the overlay buffer is limited to the size of the selected image buffer. It is not possible to draw outside those limits.

The following portion of MIL code shows the creation of the device context for the overlay buffer, the inquiring of the device context, and the drawing and writing in the overlay buffer (see also, MDispOverlay.cpp).

HDC hCustomDC;
HGDIOBJ hpen, hpenOld;
MIL_TEXT_CHAR chText[80];
SIZE  TxtSz;
RECT  Txt;
int   Count;

/* Create a device context for drawing.  */
MbufControl(MilOverlayImage, M_DC_ALLOC, M_DEFAULT);
/* Inquire the handle of the device context. */
hCustomDC = ((HDC)MbufInquire(MilOverlayImage, M_DC_HANDLE, M_NULL));
if (hCustomDC){
   /* Create a blue pen. */
   hpen=CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
   hpenOld = SelectObject(hCustomDC,hpen);

   /* Draw a cross in the overlay buffer.  */
   MoveToEx(hCustomDC,0,ImageHeight/2,NULL);
   LineTo(hCustomDC,ImageWidth,ImageHeight/2);
   MoveToEx(hCustomDC,ImageWidth/2,0,NULL);
   LineTo(hCustomDC,ImageWidth/2,ImageHeight);

   /* Write text in the overlay buffer.  */
   MosStrcpy(chText, 80, MIL_TEXT("GDI Overlay Text "));
   Count = (int) MosStrlen(chText);
   GetTextExtentPoint(hCustomDC, chText, Count, &TxtSz);

   Txt.left = (MIL_INT32)(ImageWidth*3/18);
   Txt.top  = (MIL_INT32)(ImageHeight*4/6);
   Txt.right  = (MIL_INT32)(Txt.left + TxtSz.cx);
   Txt.bottom = (MIL_INT32)(Txt.top  + TxtSz.cy);
   SetTextColor(hCustomDC,RGB(0, 0, 255));
   DrawText(hCustomDC, chText, Count, &Txt, DT_RIGHT);

   Txt.left = (MIL_INT32)(ImageWidth*12/18);
   Txt.top  = (MIL_INT32)(ImageHeight*4/6);
   Txt.right  = (MIL_INT32)(Txt.left + TxtSz.cx);
   Txt.bottom = (MIL_INT32)(Txt.top  + TxtSz.cy);
   SetTextColor(hCustomDC,RGB(255, 0, 0));
   DrawText(hCustomDC, chText, Count, &Txt, DT_RIGHT);

   /* Deselect and destroy the blue pen.  */
   SelectObject(hCustomDC,hpenOld);
   DeleteObject(hpen);
}

/* Free the created device context.  */
MbufControl(MilOverlayImage, M_DC_FREE, M_DEFAULT);

/* Signal MIL that the overlay buffer was modified.  */
MbufControl(MilOverlayImage, M_MODIFIED, M_DEFAULT);