3.49 DM_PictureHandler

With a custom graphics handler (GFX handler), images can be loaded and displayed in graphic formats not supported by the IDM. In this case whenever an image has to be loaded (e.g. because it has been attached to the application via a tile resource), the IDM first calls the registered graphics handlers. If one of these handlers can load the image, it passes the image data to the IDM and no further graphics handler is called. If no graphics handler could load the image, the IDM itself attempts to parse the image. Then the behavior is like no graphics handlers were used.

Graphics handlers are registered and unregistered with the IDM by means of the DM_PictureReaderHandler function.

A graphics handler has to be defined like this:

DM_Boolean DML_default DM_CALLBACK <ProcName>
(
  DM_PicInfo * pic
)
{
  /* custom code */
}

When called, a pointer to the structure DM_PicInfo is passed to the graphics handler. This structure contains all the information about an image that is to be loaded or whose memory is to be freed.

typedef struct {
  DM_Integer  struct_size;  // size of the structure to verify the version
  DM_UInt1    task;         // task for the GFX handler
  DM_String   fname;        // file path of the image
  DM_String   name;         // image name as indicated at tile or image
#if defined(WSIWIN)
  DM_UInt2    width;        // width of the image
  DM_UInt2    height;       // height of the image
  DM_UInt2    type;         // image type
  HANDLE      palette;      // handle for the color palette
  HANDLE      image;        // handle for the image
  HANDLE      trans_mask;   // handle for the tansparency mask
#endif
#if defined(MOTIF) || defined(QT)
  DM_UInt2    type;         // image type
  DM_Pointer  image;        // pointer to the image data
  DM_Pointer  trans_mask;   // pointer to the transparency mask
#endif
  DM_Integer  trans_color;  // index of transparent color
} DM_PicInfo;

Meaning of elements

DM_Integer struct_size

Here the size of the structure is passed. This can be used in the graphics handler to check with sizeof() whether the size of the passed structure matches the structure definition used.

DM_UInt1 task

Defines what the graphics handler should do. There are two possible tasks:

  • DM_GFX_TASK_LOAD

    Load an image.

    The graphics handler needs to load an image file with the file name fname and set the following items of the DM_PicInfo structure.

    • width (required on Microsoft Windows; otherwise contained in the image data)
    • height (required on Microsoft Windows; otherwise contained in the image data)
    • type (required)
    • palette (optional; Microsoft Windows only)
    • image (required)
    • trans_mask (optional; supported since IDM version A.05.02.e)
    • trans_color (optional; currently not evaluated)
  • DM_GFX_TASK_UNLOAD

    Free the memory of the image data.

    In this case, the following structure items are set so that the graphics handler can free the memory used by these objects:

    • palette (if existent; Microsoft Windows only)
    • image
    • trans_mask (if existent; supported since IDM version A.05.02.e)

DM_String fname

Only valid for task == DM_GFX_TASK_LOAD.

This item specifies the path and file name of the image to be loaded.

The IDM checks whether the image can be loaded. If so, fname will contain the resolved file name of the image.

If the image cannot be loaded, i.e. the file name cannot be resolved, then name == fname.

DM_String name

Only valid for task == DM_GFX_TASK_LOAD.

The item contains the unresolved file name of the image as specified at the tile resource or image object.

The structure item exists since IDM version A.05.02.e.

DM_Integer trans_color

Here the color to be displayed transparently can be passed.

The item is currently not evaluated.

Assignment of the Structure Items on Microsoft Windows

DM_UInt2 width
DM_UInt2 height

Only valid for task == DM_GFX_TASK_LOAD.

In these items the graphics handler must return the width and height of the loaded image.

DM_UInt2 type

In this item the graphics handler must return the type of the handle that is passed in image.

Value range

  • DM_GFX_BMP Windows Bitmap
  • DM_GFX_WMF Windows Meta File
  • DM_GFX_EMF Enhanced Meta File
  • DM_GFX_ICO Windows Icon

HANDLE palette

For task == DM_GFX_TASK_LOAD

The graphics handler can pass a color palette (Windows Handle Type HPALETTE) to the IDM along with the image. If this item is NULL, the system color palette is used.

In general, the use of a separate color palette for each image should be avoided, as color distortions may occur with focus changes on systems with low color depth. Instead, the graphics handler should adjust the colors of an image to the system color palette and thus ensure the color fastness of the image.

For task == DM_GFX_TASK_UNLOAD

If a color palette was used, in this element its handle is passed from the IDM to the graphics handler so that the handler can free the memory used for the color palette.

HANDLE image

For task == DM_GFX_TASK_LOAD

In this item, the graphics handler has to return the handle of the image it loaded. The type of the handle must match the one given in type.

For task == DM_GFX_TASK_UNLOAD

In this item the handle of the image, whose memory has to be freed, is passed from the IDM to the graphics handler.

HANDLE trans_mask

This structure item is only evaluated since IDM version A.05.02.e.

For task == DM_GFX_TASK_LOAD

In this element a transparency mask can be passed. The transparency mask must be a monochrome Windows Bitmap (data type HBITMAP) with the same size as the image passed in image.

A transparency mask is only supported for the image type DM_GFX_BMP, for other image types it is ignored.

For task == DM_GFX_TASK_UNLOAD

If a transparency mask was used, in this element its handle is passed from the IDM to the graphics handler so that the handler can free the memory used for the transparency mask.

Assignment of the Structure Items on Motif and Qt

DM_UInt2 type

In this item the graphics handler must return the type of the image that is passed in image.

Value Range with IDM for Motif

  • DM_GFX_XIMAGE XImage image
  • DM_GFX_PIXMAP PixMap image (supported since IDM version A.05.02.e)

Value Range with IDM for Qt

  • DM_GFX_QPIXMAP
  • DM_GFX_QIMAGE
  • DM_GFX_QICON

DM_Pointer image

For task == DM_GFX_TASK_LOAD

In this element, the graphics handler has to pass a pointer to a PixMap image or an XImage structure with the image data corresponding to the type element.

The XImage structure can be generated on X Windows with the Xlib function XCreateImage(). This requires information about current screen settings (e.g. Display, Visual, Screen, Depth). This data can be queried with the interface function DM_GetToolkitData.

For task == DM_GFX_TASK_UNLOAD

In this item a pointer to the image data, whose memory has to be freed, is passed from the IDM sto the graphics handler.

DM_Pointer trans_mask

This structure item is only evaluated since IDM version A.05.02.e.

For task == DM_GFX_TASK_LOAD

In this element a pointer to a transparency mask can be passed. On Motif the transparency mask must be a PixMap image, on Qt its data type must correspond to the image type given in type. The transparency mask must have the same size as the image passed in image.

For task == DM_GFX_TASK_UNLOAD

If a transparency mask was used, in this element a pointer to it is passed from the IDM to the graphics handler so that the handler can free the memory used for the transparency mask.

Return value

DM_TRUE

The image could be loaded.

DM_FALSE

In case of an error.

Remarks

Graphic handlers are system-dependent. As the DM_PicInfo structure shows, the data formats for returning image data differ depending on the system.

Since a graphics handler must allocate memory to load an image (e.g. for image, palette and trans_mask), it must also be charged with freeing this memory. Therefore the IDM calls the graphics handlers with task == DM_GFX_TASK_LOAD when an image is needed. If the image is no longer needed, the graphics handlers are called with task == DM_GFX_TASK_UNLOAD so that they can free the allocated memory.

The first graphics handler that frees the memory returns DM_TRUE, so no further handlers are called afterward. This does not necessarily need to be the same handler that loaded the image.

The IDM does not link an image to a graphics handler responsible for loading and releasing the image. If, for instance, all graphics handlers allocate the memory in the same way, each handler can also free the memory of any other handler. This means that the first handler called immediately frees the memory.

Example

A typical GFX handler basically has the following structure:

DM_Boolean DML_default DM_CALLBACK MyGfxHandler __1((DM_PicInfo *, pic))
{
  /* first determine what to do */
  if (pic->task == DM_GFX_TASK_LOAD) {
    /* the actual loading is done in LoadPicture_... */

#if defined(WIN32)
    /* load image (Microsoft Windows) */
    pic->image = LoadPicture_Win32 (pic->fname);
#endif
#if defined(MOTIF) || defined(QT)
    /* load image (XWindows) */
    pic->image = LoadPicture_X (pic->fname);
#endif

    if (pic->image) {
      /* write return values to pic */

#if defined(WIN32)
      pic->type    = DM_GFX_...;
      pic->palette = handle to pallet, if wanted;
      pic->width   = width of the image;
      pic->height  = height of the image;
#endif
#if defined(MOTIF) || defined(QT)
      pic->type = DM_GFX_...;
#endif

      return DM_TRUE;  /* success */
    } else {
      /* image could not be loaded, maybe another GFX handler
         or the IDM graphics parser will be more successful */
      return DM_FALSE;
    }
  } else {
    /* free memory */

#if defined(WIN32)
    if (pic->image)       /* loaded here */
      DeleteObject(pic->image);
    if (pic->palette)     /*  created here */
      DeleteObject(pic->palette);
#endif
#if defined(MOTIF) || defined(QT)
    if (pic->image)       /* loaded here */
      XDestroyImage((XImage *)pic->image);
    if (pic->trans_mask)  /*  created here */
      free(pic->trans_mask);
#endif
 
    return DM_TRUE;
  }
}

The GFX handler should be registered before loading image files and thus usually before loading the dialog:

if (!DM_PictureReaderHandler (MyGfxHandler, DMF_RegisterHandler, 0))
  DM_TraceMessage("GFX-Handler registering error", 0);
...
/* load dialog */

See also

Function DM_PictureReaderHandler