...

Chasys Draw IES Help:


SDK - File Format Plug-ins
 

Interface Rules

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

  • All file format plug-ins must be thread-safe (re-entrant); a plug-in function may be called from several threads simultaneously (especially when running with GUIs blocked). Thus, the use of global variables is highly discouraged, as is the use of __declspec(thread), which doesn't work with dynamically loaded DLLs.
  • The host may (and usually does) choose to cache (or 'hog') file format plug-ins. Your plug-in should therefore not make any assumptions about its life-span.

 

Interface Description

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

  • flt_LoadImage - Used to load images from files
  • flt_SaveImage - Used to save images to files
  • flt_CheckLoad - Used in conjunction with  flt_LoadImage
  • flt_CheckSave - Used in conjunction with  flt_SaveImage
  • flt_TransformImage - For file formats that support generic lossless transformations (e.g. JPEG)

Plug-ins are not required to implement the entire interface - you may implement flt_LoadImage alone, or implement flt_SaveImage and flt_CheckSave or all of them as you see fit.
 

Image Import via flt_LoadImage() and flt_CheckLoad()

Chasys Draw IES looks for a function named flt_LoadImage() in each plug-in it tries. If it finds this function, Chasys Draw IES first calls it with a null pointer. The plug-in should interpret this as a signal to return the number of independent file formats it can load.

This is new functionality; its purpose is to enable prioritization. It is generally expected that dedicated plug-ins will have more features than multi-format ones, and that the author of a plug-in that doesn't support the full specification/semantics for a file format would be aware of this fact.

Later, Chasys Draw IES calls flt_LoadImage() again, this time with a pointer to a flt_IMAGE_L structure. Embedded in the structure is the file name, which is stored as a unicode string (wchar_t*). The first order of business for the plug-in should be checking if the referenced file is in a format it recognizes (e.g. by checking the magic number/pattern in the file). If the file is not supported, the plug-in should immediately fail by returning PLUGIN_ERR_NO_SUPPORT to the host.

int __cdecl flt_LoadImage(flt_IMAGE_L* data);

struct flt_IMAGE_L

{

      unsigned long     width;

      unsigned long     height;

      unsigned long     pitch;

      unsigned long*    lp_pix;

//16

      wchar_t*          file;

      HWND              hwnd;

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

      unsigned char     img_type;

      unsigned char     img_subtype;

      unsigned short    unused_1;

//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_2[18];

//128

      unsigned char*    meta_data;

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

//136

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

      unsigned char     truncated;

      int               (__cdecl* set_err_info)(flt_IMAGE_L* self,wchar_t* info);

      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

};

flt_LoadImage is expected to set the width, height and where applicable, x_pos, y_pos, options, transparency and name members, then call the create() member function to request Chasys Draw IES to allocate the bitmap for each layer in the image. This process is repeated until all layers have been loaded.

create() takes the flt_IMAGE_L object as a parameter and 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, it allocates a smaller bitmap of the same aspect ratio, sets width and height to the new values, then returns a negative value. 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_BAD_PARAM.

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 flt_LoadImage) 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, the plug-in should set truncated to 1 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_err_info if it is not zero.

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.

If the plug-in generates metadata (a.k.a. layer attachments), the metadata archive handle should be passed to the create() function via the meta_data parameter. If the create() succeeds, the host is responsible for freeing the memory handle, otherwise, the plug-in must free the handle. If the plug-in doesn't know how to create an archive, it can pass the metadata entry by entry after calling create() by setting meta_data to the memory location of the data and calling the meta_write() function with the size and type of 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 using the second method (or not setting metadata) you must ensure meta_data is set to zero before calling create().

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_LAYERED 0x00000000
PLUGIN_IMGTYPE_MULTIRES 0x00000001
PLUGIN_IMGTYPE_ANIMATION

0x00000002

   
PLUGIN_IMGSUBTYPE_NORMAL

0x00000000

PLUGIN_IMGSUBTYPE_CLIPPED 0x00000001
PLUGIN_IMGSUBTYPE_MULTIRES 0x00000001
PLUGIN_IMGSUBTYPE_ONIONSKIN 0x00000001

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

LAYER_BLEND_NORM /* Blend mode = Alpha blend */ 0x00000000
LAYER_BLEND_ADD /* Blend mode = Add */ 0x00000001
LAYER_BLEND_SUB /* Blend mode = Subtract */ 0x00000002
LAYER_BLEND_MUL /* Blend mode = Multiply */ 0x00000003
LAYER_BLEND_OVER /* Blend mode = Overlay */ 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_OPTION_HIDDEN /* Hidden layer */ 0x00000100
LAYER_OPTION_LOCKED /* Locked layer */ 0x00000200
LAYER_OPTION_EXCLUDED /* Excluded layer */ 0x00000400
LAYER_OPTION_PROTECT /* Alpha-protected layer */ 0x00000800
LAYER_OPTION_CLICKTHRU /* Click-thru layer */ 0x00001000
LAYER_OPTION_FLOATING /* Floating layer */ 0x00002000

 

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.

 

IMPORTANT:

The following function must also be supported (failure to which the plug-in will be treated as low priority):

int __cdecl flt_CheckLoad(flt_CHECK_L* info); /* introduced in FastExternals 3 rev 22 */

struct flt_CHECK_L

{

      wchar_t*          extension[32];

      unsigned char     hdr_data[32];

      unsigned long     hdr_size;

      unsigned char     reserved_1[128-4-100];//do not touch

      unsigned char     level_image;

      unsigned char     level_layer;

      unsigned char     level_other;

      unsigned char     support_flags;

};

#define SUPPORT_FLAG_IS_BRIDGE     0x00000001
#define SUPPORT_FLAG_DEMOTE_ME     0x00000002

This is the function that Chasys Draw IES calls to check if the plug-in can load files in the specified file format. Chasys Draw IES may provide the file extension (e.g. “.jpg”), and/or up to the first 32 bytes of the file data. If provided, the extension always begins with a dot. The plug-in should use this information to check if it supports that file. If it finds that it support the file, it should set up the appropriate support data as outlined under support levels then return 1. If not, it should return 0.

So as to keep rogue plug-ins at bay, Chasys Draw IES will send test data to this function from time to time, just to see whether or not it is implemented properly. Plug-ins that fail the test will be blacklisted by the application.

 

Image Export via flt_SaveImage() and flt_CheckSave()

Chasys Draw IES calls flt_SaveImage 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 if GUIs are allowed. The first order of business for the plug-in should be checking if the file extension is a type it supports (preferably by calling flt_CheckSave() internally). If the file extension is not supported, the plug-in should immediately fail by returning PLUGIN_ERR_NO_SUPPORT to the host.

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 flt_SaveImage(flt_IMAGE_S* data);

struct flt_IMAGE_S

{

      unsigned long     width;

      unsigned long     height;

      unsigned long     pitch;

      unsigned long*    lp_pix;

//16

      wchar_t*          file;

      HWND              hwnd;

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

      unsigned char     img_type;

      unsigned char     img_subtype;

      unsigned short    unused_1;

//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_2[18];

//128

      unsigned char*    meta_data;

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

//136

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

      unsigned char     truncated;

      int               (__cdecl* set_err_info)(flt_IMAGE_S* self,wchar_t* info);

      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

};

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.

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 saves the current layer, 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 layers have been saved. Please note that the select() member may be null if there's only one layer.

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

The plug-in should return the number of layers saved (greater than 0) if it succeeds. Failure is indicated by returning the relevant PLUGIN_ERR_* code (these codes are defined in plugin.h). Error details may be provided via set_err_info if it is not zero.

IMPORTANT:

The following function must also be supported (failure to which the plug-in will be rejected):

int __cdecl flt_CheckSave(flt_CHECK_S* info); /* introduced in FastExternals 3 rev 22 */

struct flt_CHECK_S

{

      wchar_t*          extension[32];

      unsigned char     reserved_1[128-4-64];//do not touch

      unsigned char     level_image;

      unsigned char     level_layer;

      unsigned char     level_other;

      unsigned char     support_flags;

};

This is the function that Chasys Draw IES calls to check if the plug-in can save files in the specified file format. Chasys Draw IES will provide the file extension (e.g. “.jpg”). The extension provided always begins with a dot. The plug-in should use this information to check if it supports that file. If it finds that it support the file, it should set up the appropriate support data as outlined under support levels then return 1. If not, it should return 0.

So as to keep rogue plug-ins at bay, Chasys Draw IES will send test data to this function from time to time, just to see whether or not it is implemented properly. Plug-ins that fail the test will be blacklisted by the application.

 

Generic Transformation via flt_TransformImage()

Some lossy file formats, such as JPEG, support some generic transformations which are carried out losslessly without recompressing the image. This functionality may be exposed through the flt_TransformImage() call. It takes a pointer to a structure of type flt_IMAGE_X. Embedded in this structure is the unicode filename and transformation identifier:

int __cdecl flt_TransformImage(flt_IMAGE_X* data);

struct flt_IMAGE_X

{

      wchar_t*          file;

      HWND              hwnd;

      unsigned long     xform_id;

      unsigned long     xform_id2;

//16

      unsigned char     reserved_1[256-16-(1+4+4)];//do not touch

      unsigned char     unused_1;

      int               (__cdecl* set_err_info)(flt_IMAGE_X* self,wchar_t* info);

      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

};

 

The file member contains the file to be transformed. One of the following constants must be specified for the xform_id parameter:

PLG_FLT_XFORM_ROTATE_090 0x00000001
PLG_FLT_XFORM_ROTATE_180 0x00000002
PLG_FLT_XFORM_ROTATE_270 0x00000003
PLG_FLT_XFORM_FLIP_H 0x00000004
PLG_FLT_XFORM_FLIP_V 0x00000005
PLG_FLT_XFORM_TRANSPOSE 0x00000006
PLG_FLT_XFORM_TRANSVERSE 0x00000007

The function should return a value greater than zero if the transformation was done. Failure is indicated by returning the relevant PLUGIN_ERR_* code (these codes are defined in plugin.h). Error details may be provided via set_err_info if it is not zero.

Plug-ins that implement lossless file formats must never implement this function, so as to allow the host to use its own methods.

Never emulate this function, i.e. by loading the file, transforming the image then saving. This is considered rogue behaviour and will cause your plug-in to be blacklisted as "image destructive content".

Chasys Draw IES currently uses a file-type white-list to decide whether or not to call this function. As such, you should report to the author when you make a plug-in implementing it so that you file format may be added to the white-list. Currently, only JPEG and JPEG-2000 files are allowed through.

 

Support Levels

Support Levels indicate how well a plug-in supports a specific file format, with 0 indicating no support (or "not sure") and 255 indicating full support including all semantics. The support level is calculated as shown below; the exact values used are at the discretion of the plug-in author. Plug-ins that do not directly load the image (and can therefore not guarantee a specific level of support) should always specify the SUPPORT_FLAG_IS_BRIDGE flag to allow plug-ins that are specifically designed for those file formats to take precedence.

The level_image member should be set to a value between 0 and 255 depending on the completeness of image data decoding implemented by the plug-in. If this value is zero, Chasys Draw IES will assume that the plug-in cannot guarantee any level of support and will use it only after everything else has failed.

Complete support for the file format including all variations (animated, still, different formats, etc.) 255
Support for the most common variations of the file format 128 - 254
Support for some varieties of the file format 1 - 127
No support for the image semantics of the file format 0

The level_layer member should be set to a value between 0 and 255 depending on the completeness of multi-layer/multi-frame decoding implemented by the plug-in. If the plug-in can only decode the first frame/layer, it should set this memeber to zero.

Complete support for structures such as layers, frames, pages, multi-resolution copies, etc. 255
Support for the most common structures 128 - 254
Support for some some structures 1 - 127
No support for structured images (i.e. flat images only with no layers/frames/pages) 0

The level_other member should be set to a value between 0 and 255 depending on the completeness of metadata decoding implemented by the plug-in. Metadata may include thing such as EXIF data, vector data, etc.

Complete support for other metadata/information such as EXIF, paths, vectors, etc. 255
Support for the most common metadata 128 - 254
Support for some metadata 1 - 127
No support for metadata 0

The support_flags member should be set to the logical OR of the appropriate flags.

A bridge plug-in, i.e. one that loads image by calling another module, such as decoding capabilities provided by the OS (e.g. OLE/LoadPicture) SUPPORT_FLAG_IS_BRIDGE
Plug-in should be intentionally given a low priority (e.g. it employs an inefficient decoding mechanism) SUPPORT_FLAG_DEMOTE_ME
Sample Code

Here's the full listing of the main file for the PNG plug-in included with Chasys Draw IES for your reference:

View “flt_PNG.cpp”

TAGS: Chasys Draw IES Source Code, PNG File Format Plug-in

You can also view other source code files here.

 

 

Copyright © John Paul Chacha, 2001-2017

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