...

Online Help for Chasys Draw IES: SDK - Device Plug-ins


SDK - Device Plug-ins
 

Interface Rules

The following rules apply to all plug-ins implementing this interface:

  • Device plug-ins need not be re-entrant. This interface is always called from a single thread as it requires a GUI.
  • The interface currently only allows the plug-in to access one layer per call; this layer is chosen by the user during plug-in invocation
  • The plug-in should allow the user to set any necessary parameters via an appropriate dialog box.
  • The image buffer for this interface is prelocked, and can be accessed at any time

 

Interface Description

The file format plug-in interface is made up of three functions in addition to the general interface:

  • dev_ReadImage - Used to read images from external devices
  • dev_SendImage - Used to send images to external devices

Plug-ins are not required to implement the entire interface - you may implement dev_ReadImage, or dev_SendImage or both of them as you see fit.

 

Image Import via dev_ReadImage()

Chasys Draw IES looks for a function named dev_ReadImage() in the plug-in the user selects. If it finds this function, Chasys Draw IES calls it with a pointer to a dev_IMAGE_R structure.

int __cdecl dev_ReadImage(dev_IMAGE_R* data);

struct dev_IMAGE_R

{

      unsigned long     width;

      unsigned long     height;

      unsigned long     pitch;

      unsigned long*    lp_pix;

//16

      wchar_t*          title_or_path;

      HWND              hwnd;

      int               (__cdecl* create)(dev_IMAGE_R* self);

      unsigned short    host_flags;

      unsigned char     img_type;

      unsigned char     img_subtype;

//32

      unsigned long     layer_count;

      short             x_pos;

      short             y_pos;

      wchar_t           name[32];

      unsigned short    options;

      unsigned short    frame_delay;

      unsigned char     group_id;

      unsigned char     transparency;

      unsigned char     unused_1[18];

//128

      unsigned char*    meta_data;

      int               (__cdecl* meta_write)(dev_IMAGE_R* self,char* type,int size);

//136

      unsigned char     reserved_1[256-136-(5*4)]; //do not touch

      int               (__cdecl* set_infostr)(dev_IMAGE_R* self,int type,const wchar_t* info);

      int               (__cdecl* set_progress)(dev_IMAGE_R* self,int done,int total);

      int               host_response;

      unsigned short    warnings;

      unsigned char     reserved_2[2]; //do not touch

      unsigned long     timeout;

//256

      pi_STATESTORE*    pi_StateStore;

      pi_METAMARKUP*    pi_MetaMarkup;

      pi_BASICQUERY*    pi_BasicQuery;

      pi_BASICIMAGE*    pi_BasicImage;

      pi_BASICCOLOR*    pi_BasicColor;

      pi_BASICUTILS*    pi_BasicUtils;

//280

      unsigned char     reserved_x[1024-280];//do not touch

};

dev_ReadImage() is expected to set the width and height members, then call the create() member function to request Chasys Draw IES to allocate the bitmap for each layer in the image.

create() returns non-zero to indicate success. It also sets the width, height, pitch (in number of pixels, not bytes) and lp_pix. If the requested size is too large for the host to allocate and host_flags contains PLUGIN_HOSTFLAG_RESIZE, it attempts to allocate a smaller bitmap of the same aspect ratio, sets width and height to the new values, then leaves PLUGIN_HOSTFLAG_RESIZE set (normally, it is cleared). In this case, the host requires that the plug-in resizes the image locally. Your plug-in should either resize the loaded image internally without assistance from the host, or indicate failure by returning the error code PLUGIN_ERR_BITMAP_BIG. On failure, create() returns zero and sets host_response to the appropriate PLUGIN_ERR_* code.

The plug-in proceeds to fill lp_pix as an array of 32 bit integers, each representing a pixel in BGRA format (blue LSB, alpha MSB), with alpha values of zero (0x00) for opaque and 255 (0xff) for transparent.

If the image has additional layers, the plug-in sets width, height, etc, then calls create() again; this is repeated until all the layers have been loaded.

The plug-in returns (from dev_ReadImage) the number of layers loaded (greater than 0) to indicate success. If the image had more layers but the plug-in was unable to load them due to internal or host constraints, it should add the relevant PLUGIN_WARN_* flag to warnings to inform the host that the image may be incomplete. Failure is indicated by returning the relevant PLUGIN_ERR_* code (these codes are defined in plugin.h). Error details may be provided via set_infostr() if it is not zero by setting type to PLUGIN_INFOTYPE_ERROR and providing the error string.

Progress data may be shared with the host via set_progress() if it is not zero. It is up to the host to decide what to do with the progress information. A zero return from set_progress() indicates that the user wishes to cancel the operation. The plug-in should respond to this be immediately ceasing all operations and returning PLUGIN_ERR_USER_CANCEL.

The color-space is always sRGB. You are not required to perform any color matching except converting colors to sRGB if the file format uses another color-space. You can use pi_BasicColor to perform this and many other conversions.

The hwnd member being set to a valid handle (non-zero) is an indication to the plug-in that it is free to display a dialog box. Do not display a user interface of any sort if this member is zero. Device plugins that must show dialogs should interpret this as an error and return 0.

If the plug-in generates metadata (a.k.a. layer attachments), it should pass the metadata entry by entry after calling create() by calling the meta_write() function with the size and type of data and optionally setting meta_data to the memory location of the data, e.g. calling meta_write(data,"MARK",256) will create an attachment of type MARK and write 256 bytes of data into it from meta_data. If meta_data is set to zero before calling meta_write() and a non-zero size is provided, Chasys Draw IES will create null metadata of the specified size and type and return the pointer in meta_data.

It is no longer necessary to set meta_data to zero before calling create(). To pass or request a metadata archive in a plug that knows how to handle archives, use the standard metadata functions with the archive four character code. The ability to provide or accept raw archives is an optional host feature that may not be available in all scenarios.

Please note that the metadata function pointers can be zero if the interface is not implemented or is disabled by the user. Also note that errors result in zero returns. The plug-in is expected to degrade gracefully in these circumstances.

These are the flags for the img_type and img_subtype members (this list is not exhaustive. See plugin.h for complete list):

PLUGIN_IMGTYPE_COMPOSITE 0x0000
PLUGIN_IMGTYPE_IMAGELIST 0x0001
PLUGIN_IMGTYPE_FRAMEANIM

0x0002

PLUGIN_IMGTYPE_OBJECTANIM

0x0003


PLUGIN_IMGSUBTYPE_NORMAL

0x0000

PLUGIN_IMGSUBTYPE_CLIPPED 0x0001
PLUGIN_IMGSUBTYPE_MIPMAP 0x0001
PLUGIN_IMGSUBTYPE_ONIONSKIN 0x0001

The options member a combination of zero or more of the LAYER_OPTION_* flags below and exactly one of the LAYER_BLEND_* flags (this list is not exhaustive; see layerdefs.h for complete list):

LAYER_OPTION_HIDDEN /* Hidden layer */ 0x00000100
LAYER_OPTION_LOCKED /* Locked layer */ 0x00000200
LAYER_OPTION_EXCLUDED /* Excluded layer */ 0x00000400
LAYER_OPTION_PROTECTED /* Alpha-protected layer */ 0x00000800
LAYER_OPTION_CLICKTHRU /* Click-thru layer */ 0x00001000
LAYER_OPTION_FLOATING /* Floating layer */ 0x00002000

LAYER_BLEND_NONE /* Blend mode = None */ 0x000000ff
LAYER_BLEND_USER /* Blend mode = User Defined */ 0x000000fe
LAYER_BLEND_NORM /* Blend mode = Normal */ 0x00000000
LAYER_BLEND_ADD /* Blend mode = Add */ 0x00000001
LAYER_BLEND_SUB /* Blend mode = Subtract */ 0x00000002
LAYER_BLEND_MUL /* Blend mode = Multiply */ 0x00000003
LAYER_BLEND_OFF /* Blend mode = Offset */ 0x00000004
LAYER_BLEND_HUE /* Blend mode = Hue */ 0x00000005
LAYER_BLEND_CLR /* Blend mode = Chroma */ 0x00000006
LAYER_BLEND_LUM /* Blend mode = Luma */ 0x00000007
LAYER_BLEND_SCRN /* Blend mode = Screen */ 0x00000008
LAYER_BLEND_MASK /* Blend mode = Mask */ 0x00000009
LAYER_BLEND_DIV /* Blend mode = Divide */ 0x0000000a
LAYER_BLEND_DIFF /* Blend mode = Difference */ 0x0000000b
LAYER_BLEND_MIN /* Blend mode = Minimum */ 0x0000000c
LAYER_BLEND_MAX /* Blend mode = Maximum */ 0x0000000d
LAYER_BLEND_SAT /* Blend mode = Saturation */ 0x0000000e
LAYER_BLEND_OVER /* Blend mode = Overlay */ 0x0000000f
LAYER_BLEND_DODG /* Blend mode = Dodge */ 0x00000010
LAYER_BLEND_BURN /* Blend mode = Burn */ 0x00000011
LAYER_BLEND_VAL /* Blend mode = Value */ 0x00000012
LAYER_BLEND_LIT /* Blend mode = Lightness */ 0x00000013
LAYER_BLEND_AND /* Blend mode = Logical AND */ 0x00000014
LAYER_BLEND_OR /* Blend mode = Logical OR */ 0x00000015
LAYER_BLEND_XOR /* Blend mode = Logical XOR */ 0x00000016
LAYER_BLEND_LMSK /* Blend mode = Luma Mask */ 0x00000017
LAYER_BLEND_BHND /* Blend mode = Behind */ 0x00000018
LAYER_BLEND_OPNT /* Blend mode = Overpaint */ 0x00000019

 The following may be used in combination for the host_flags member (this list is not exhaustive. See layerdefs.h for complete list):

PLUGIN_HOSTFLAG_RESIZE /* host may return resized image if necessary */ 0x0001
PLUGIN_HOSTFLAG_NO_SAVE /* ask host to treat file format as read-only, i.e redirect save to another format */ 0x0002
PLUGIN_HOSTFLAG_MORE_TIME /* ask host to defer time-out (e.g. plug-in was showing UI; set this immediately after the user closes the UI) */ 0x0004
PLUGIN_HOSTFLAG_WANT_THUMB /* plug-in may return a thumbnail if the image cannot be retrieved quickly */ 0x0100
PLUGIN_HOSTFLAG_SKIP_META /* plug-in may omit metadata if retrieval is difficult */ 0x0200
PLUGIN_HOSTFLAG_SKIP_ANIM /* plug-in may omit animation because the host will not animate */ 0x0400

The following may be used in combination for the warnings member (this list is not exhaustive. See layerdefs.h for complete list):

PLUGIN_WARN_LAYER_COUNT /* layers exceed allowed maximum */ 0x0001
PLUGIN_WARN_LAYER_TYPE /* bad or unknown layer type found */ 0x0002
PLUGIN_WARN_BLEND_MODE /* bad or unknown blend-mode found */ 0x0004
PLUGIN_WARN_IMAGE_DATA *** /* bad or unknown image data found */ 0x0008
PLUGIN_WARN_ALPHA_DROP /* transparency info removed */ 0x0010
PLUGIN_WARN_THUMB_ONLY /* the operation timed out */ 0x0020
PLUGIN_WARN_NONSTANDARD /* non-standard extension/feature used */ 0x0080
PLUGIN_WARN_TIMEOUT /* the operation timed out */ 0x0100

Data corruption should generally be treated as a permanent error that causes the loading process to fail with the appropriate PLUGIN_ERR_ error code. The PLUGIN_WARN_IMAGE_DATA option should only be used by experimental plug-ins that support file formats for which better support is known not to exist and for which some data corruption may be acceptable.

If the timeout member is non-zero, the plug-in has that many milliseconds to finish the operation. Chasys Draw IES may enforce this timeout by, for example, refusing to honour create() requests after the timeout period. In this case, Chasys Draw IES will add PLUGIN_WARN_TIMEOUT to warnings.

Chasys Draw IES may advise the plug-in that a thumbnail is okay if the full image will take long to retrieve by setting PLUGIN_HOSTFLAG_WANT_THUMB. If the plug-in elects to only provide a thumbnail, PLUGIN_WARN_THUMB_ONLY must be added to warnings.

The maximum allowed number of layers is application-dependent. If create() fails, your plug-in should abort decoding. Do not attempt to perform any memory management functions (like de-allocation or page-locking) on lp_pix.

 

Image Export via dev_SendImage()

Chasys Draw IES calls dev_SendImage() with all the members set; i.e. width, height, pitch (in number of pixels, not bytes) and lp_pix are set to describe the bitmap, file to the save path, and hwnd to the parent window. Initially, layer_count will be set to the number of layers in the image.

Initially, layer_count will be set to the number of layers in the image. If your plug-in does not support layers, or layer_count is greater than what your plug-in can handle, you should abort immediately by returning PLUGIN_ERR_NOT_FLAT. The host will then flatten the image for you and call flt_SaveImage() again with the flattened image and a layer_count of 1.

int __cdecl dev_SendImage(dev_IMAGE_S* data);

struct dev_IMAGE_S

{

      unsigned long     width;

      unsigned long     height;

      unsigned long     pitch;

      unsigned long*    lp_pix;

//16

      const wchar_t*    title_or_path;

      HWND              hwnd;

      int               (__cdecl* select)(dev_IMAGE_S* self,int layer_id);

      unsigned short    host_flags;

      unsigned char     img_type;

      unsigned char     img_subtype;

//32

      unsigned long     layer_count;

      short             x_pos;

      short             y_pos;

      wchar_t           name[32];

      unsigned short    options;

      unsigned short    frame_delay;

      unsigned char     group_id;

      unsigned char     transparency;

      unsigned char     unused_1[18];

//128

      unsigned char*    meta_data;

      int               (__cdecl* meta_read)(dev_IMAGE_S* self,char* type);

//136

      unsigned char     reserved_1[256-136-(5*4)]; //do not touch

      int               (__cdecl* set_infostr)(dev_IMAGE_S* self,int type,const wchar_t* info);

      int               (__cdecl* set_progress)(dev_IMAGE_S* self,int done,int total);

      int               host_response;

      unsigned short    warnings;

      unsigned char     reserved_2[2]; //do not touch

      unsigned long     timeout;

//256

      pi_STATESTORE*    pi_StateStore;

      pi_METAMARKUP*    pi_MetaMarkup;

      pi_BASICQUERY*    pi_BasicQuery;

      pi_BASICIMAGE*    pi_BasicImage;

      pi_BASICCOLOR*    pi_BasicColor;

      pi_BASICUTILS*    pi_BasicUtils;

//280

      unsigned char     reserved_x[1024-280];//do not touch

};

As usual, lp_pix is an array of 32 bit integers, each representing a pixel in BGRA format (blue LSB, alpha MSB), with alpha values of zero (0x00) for opaque and 255 (0xff) for transparent. It should not be altered by the plug-in in any way. The plug-in, if capable of storing alpha data, should check all pixels to determine whether or not the alpha values are used (i.e. some are non-zero). If the plug-in is capable of handling layered images, it should check the transparency value as well.

If the image has metadata, the meta_data parameter will be a non-zero metadata archive handle. The host owns this memory handle; the plug-in should not free or change it. If the plug-in doesn’t know how to process a metadata archive, it can call the meta_read() function to load specific metadata elements into meta_data, e.g. calling meta_read(data,"MARK") will load the markup attachment if available. The function returns the size of the metadata or zero if the type is not found. Setting type to zero will load the entire metadata archive.

After the plug-in sends the current frame, it calls select() with the zero-based identifier of the next layer to retrieve it; the data for which is placed in the width, height, pitch and lp_pix members. This is repeated until all the frames have been sent. Please note that the select() member may be null if there’s only one layer. Some hosts allow specifying “-1” to return the merged image with limited functionality and without any metadata. If you use this extension, be sure to call select() again with a valid layer identifier before calling any other function.

The img_type and options members have the same meanings are described above.

The plug-in should return the number of layers sent (greater than 0) if it succeeds. If the image had more layers but the plug-in was unable to send them due to internal or host constraints, it should add the relevant PLUGIN_WARN_* flag to warnings to inform the host that the image may be incomplete. Failure is indicated by returning the relevant PLUGIN_ERR_* code (these codes are defined in plugin.h).

Progress data may be shared with the host via set_progress() if it is not zero. It is up to the host to decide what to do with the progress information. A zero return from set_progress() indicates that the user wishes to cancel the operation. The plug-in should respond to this be immediately ceasing all operations and returning PLUGIN_ERR_USER_CANCEL.

 

 

Copyright © John Paul Chacha, 2001-2023

The information herein is subject to change without any notice. The author makes no guarantees as to the completeness of this documentation.