ImageFilterHandler ItemMotionHandler Classes Table of Contents

ImageLoader
ImageSaver


/*
 * Image Pixel Datatypes.
 */
typedef enum en_LWImageType {
   LWIMTYP_RGB24 = 0,
   LWIMTYP_GREY8,
   LWIMTYP_INDEX8,
   LWIMTYP_GREYFP,
   LWIMTYP_RGBFP,
   LWIMTYP_RGBA32,
   LWIMTYP_RGBAFP,
   LWIMTYP_SPECIAL
} LWImageType;

/*
 * Image Pixel Structures.
 */
typedef void *    LWPixelID;

typedef struct st_LWPixelRGB24 {
   unsigned char    r;
   unsigned char    g;
   unsigned char    b;
} LWPixelRGB24;

typedef struct st_LWPixelRGBFP {
   float            r;
   float            g;
   float            b;
} LWPixelRGBFP;

typedef struct st_LWPixelRGBA32 {
   unsigned char    r;
   unsigned char    g;
   unsigned char    b;
   unsigned char    a;
} LWPixelRGBA32;

typedef struct st_LWPixelRGBAFP {
   float            r;
   float            g;
   float            b;
   float            a;
} LWPixelRGBAFP;


/*
 * Image Buffer Protocol with parameter tags.
 */
typedef int     LWImageParam;
#define IMTAG_WIDTH   1
#define IMTAG_HEIGHT  2
#define IMTAG_ASPECT  3
#define IMTAG_NUMCOLORS  4

typedef union un_LWImageProtocol {
   int        type;
   void      *priv_data;
   int      (*done)      (void *, int);
   void     (*setParam)  (void *, LWImageParam, int, float);
   int      (*sendLine)  (void *, int, const LWPixelID);
   void     (*setMap)    (void *, int, const unsigned char[3]);
} LWImageProtocol, *LWImageProtocolID;


/*
 * "ImageLoader" local struct.
 */
typedef struct st_LWImageLoaderLocal {
   void        *priv_data;
   int          result;
   const char     *filename;
   LWMonitor      *monitor;
   LWImageProtocolID (*begin) (void *, LWImageType);
   void       (*done)  (void *, LWImageProtocolID);
} LWImageLoaderLocal;

/*
 * "ImageSaver" local struct.
 */
typedef struct st_LWImageSaverLocal {
   void      *priv_data;
   int        result;
   LWImageType   type;
   const char   *filename;
   LWMonitor    *monitor;
   int      (*sendData) (void *, LWImageProtocolID, int flags);
} LWImageSaverLocal;

#define IPSTAT_OK  0
#define IPSTAT_NOREC  1
#define IPSTAT_BADFILE   2
#define IPSTAT_ABORT  3
#define IPSTAT_FAILED   99

#define IMGF_REVERSE (1<<0)

#define IP_SETPARAM(p,t,i,f)  (*(p)->setParam) ((p)->priv_data,t,i,f)
#define IP_WIDTH(p,w)      IP_SETPARAM (p, IMTAG_WIDTH, w, 0.0)
#define IP_HEIGHT(p,h)     IP_SETPARAM (p, IMTAG_HEIGHT, h, 0.0)
#define IP_ASPECT(p,a)     IP_SETPARAM (p, IMTAG_ASPECT, 0, a)
#define IP_NUMCOLORS(p,n)  IP_SETPARAM (p, IMTAG_NUMCOLORS, n, 0.0)
#define IP_SENDLINE(p,ln,d)   (*(p)->sendLine) ((p)->priv_data,ln,d)
#define IP_SETMAP(p,i,val) (*(p)->setMap) ((p)->priv_data,i,val)
#define IP_DONE(p,err)     (*(p)->done) ((p)->priv_data,err)


1. Introduction

This module provides interfaces for dealing with image types commonly employed by LightWave users. This allows the loading and saving of large, deep images in an expandable set of formats, and for accessing the data in a uniform manner regardless of the underlying data format. This interface is designed with plug-in image loaders and savers in mind and it provides some built-in IFF format support.

Image types are given by the following values. RGB24 is an image with eight bits each of red, green and blue data for each pixel. GREY8 is an image with eight bits of greyscale value at each pixel. INDEX8 is an image with up to eight bits of color index at each pixel, mapped through a 24 bit color table.

(1) Public declarations

       #define IMG_RGB24       0
       #define IMG_GREY8       1
       #define IMG_INDEX8      2
       . . .
Image color component, grey or index values are all unsigned chars scaled from 0 to 255.

(2) Public forward definitions

       typedef unsigned char            ImageValue;
       . . .

2. Image I/O Server Interface

The image input and output interfaces are designed to be extended with plug-in loaders and savers. As result, each interface really only defines the local data structure for the activation function.

2.1. Image Loaders

Image loaders are servers that are called sequentially until one is able to load the image file. An application will normally have a standard format in which images are saved, so that will normally be tried first after which other loaders may be tried in any order the host can determine. If loaders are just scanned in the host plug-in database they will be called in something like alphabetical order.

The activation call for a loader gets passed a pointer to a filename as well as callbacks for image data transfer. If the loader cannot open the file it sets the `result' field to IPSTAT_BADFILE and returns. If it does not recognize the file format, it sets the result to IPSTAT_NOREC. If it can load the image, it calls the `begin' callback with type of image protocol it would like. The loader then sends the data from the file to the host through the protocol and calls the `done' callback when complete to allow the source to dispose of the protocol. These callbacks are called with the `priv_data' pointer as the first field.

(3) Public types

       typedef struct st_ImLoaderLocal {
          void             *priv_data;
          int               result;
          const char       *filename;
          Monitor          *monitor;
          ImageProtocolID (*begin) (void *, int type);
          void            (*done) (void *, ImageProtocolID);
       } ImLoaderLocal;
       . . .

2.2. Image Savers

Image savers are servers of "ImageSaver" class that write an image out to a file in a single specific format. The save format is typically chosen directly by the user with an interface showing the user names for the servers, so no scanning or ordering is required.

The activation call for savers gets a filename, a requested protocol type, and a callback for the host to output its image data to the saver protocol. The flag in the `sendData' callback can contain the IMGF_ALPHA bit if the saver can store alpha data and IMGF_REVERSE bit if the saver wants the data sent bottom to top rather than top to bottom. The saver should create a protocol and set flags most appropriate for the destination file format. The `sendData' callback will return a non-zero error code if anything failed on the sending end or if the destination reports an error.

(4) Public types

       . . .
       typedef struct st_ImSaverLocal {
          void            *priv_data;
          int              result;
          int              type;
          const char      *filename;
          Monitor         *monitor;
          int            (*sendData) (void *, ImageProtocolID, int);
       } ImSaverLocal;
       . . .

2.3. Result Value

The result value indicates the status of the loader or saver upon completion. If the load or save was sucessful, the value should be IPSTAT_OK. If a loader fails to recognize a file as something it can load it should set the result to IPSTAT_NOREC. If the server could not open the file it should return IPSTAT_BADFILE. Any other error is just a generic failure of the loader or saver and so should set the result to IPSTAT_FAILED. Other failure modes might be possible if required in the future.

(5) Public declarations

       . . .
       #define IPSTAT_OK                0
       #define IPSTAT_NOREC             1
       #define IPSTAT_BADFILE           2
       #define IPSTAT_ABORT             3
       #define IPSTAT_FAILED           99
       . . .

2.4. Image Transfer Protocols

Images are passed from source to destination using an image protocol. Typically, the source will select the protocol type and the destination will create a protocol of that type. The source will then send the image data to the source by calling callbacks in the protocol. Both ends are then given an opportunity to clean up. This is called a pusher protocol since the source "pushes" the data at the destination rather than the destination pulling it.

There are two protocols for the three types of images: color and index protocols. The protocol `type' can have any of the same values as image type and determines the callbacks in the protocol and what they do. Protocols contain a private data pointer which should be passed as the first argument to all the callbacks.

2.4.1. Color Protocol

The color protocol is used for the RGB and grey valued images (RGB24 and GREY8 types). The source starts the output by calling the `setSize' function with the width and height of the image and flags. The flags can contain the IMGF_ALPHA bit to indicate that the source data contains an alpha channel. The source then sends the data by calling the `sendLine' function with each image row number and a pointer to a line of image data and a line of alpha data, if any was indicated. For greyscale images, the image line consists of one image value per column in the image (G1 G2 ... Gw). For RGB images, this line data consists of three image values per column of the image in RGB order (R1 G1 B1 R2 G2 B2 ... Rw Gw Bw). The alpha data is in greyscale format.

(6) Public types

       . . .
       typedef struct st_ColorProtocol {
          int              type;
          void            *priv_data;
          void           (*setSize) (void *, int, int, int);
          int            (*sendLine) (void *, int, const ImageValue *,
                  const ImageValue *);
          int            (*done) (void *, int);
       } ColorProtocol;
       . . .

2.4.2. Index Protocol

Colormap index images use the index protocol. The source must first call `setSize' and `numColors' with image size, flags and number of entries in the colormap. The source must then set the colormap by calling the `setMap' callback for each entry in the colormap. Any entry which is not set is left undefined. The data in the image is then filled in using the `sendLine' function just like the greyscale case except that the image values are not grey values but colormap indices. Alpha values are in greyscale data format.

(7) Public types

       . . .
       typedef struct st_IndexProtocol {
          int              type;
          void            *priv_data;
          void           (*setSize) (void *, int, int, int);
          void           (*numColors) (void *, int);
          void           (*setMap) (void *, int, const ImageValue[3]);
          int            (*sendLine) (void *, int, const ImageValue *,
                  const ImageValue *);
          int            (*done) (void *, int);
       } IndexProtocol;
       . . .

2.4.3. Generic Protocol

The generic protocol is either of these possibilities plus the type field for easy type identifcation.

(8) Public types

       . . .
       typedef union un_ImageProtocol {
          int              type;
          ColorProtocol    color;
          IndexProtocol    index;
       } ImageProtocol;

(9) Public forward definitions

       . . .
       typedef union un_ImageProtocol  *ImageProtocolID;

2.4.4. Error Handling

There are two specific mechanisms for dealing with errors that occur while using image protocols. The destination can return error codes from the `sendLine' and `done' callbacks, and the source can pass an error code to the destination's `done' callback.

If an error occurs in the source of a protocol, such as a failure partway though reading a file, the source can stop calling `sendLine' prematurely. This will often trigger an error in the destination since it will have been keeping track of the amount of data sent. The source should then also pass a non-zero error code to the `done' callback which will signal an error to the destination.

If an error occurs in the destination of a protocol, such as a failure partway through saving an image, the destination should start to return a non-zero error code from `sendLine.' A well-written source will stop sending data when this happens, but the destination should be prepared to continue to get lines of data and to continue to return an error code. A failed destination should also return a non-zero error code from the `done' callback.

2.4.5. Misc Types

Flags to be passed to `setSize' and `sendData' callbacks.

(10) Public declarations

       . . .
       #define IMGF_ALPHA               1
       #define IMGF_REVERSE             2
       . . .
There are also some protocol macros defined to get the whole calling interface right.

(11) Public declarations

       . . .
       #define IP_SETSIZE(p,w,h,f)     (*(p)->setSize) ((p)->priv_data,w,h,f)
       #define IP_NUMCOLORS(p,n)       (*(p)->numColors) ((p)->priv_data,n)
       #define IP_SETMAP(p,i,val)      (*(p)->setMap) ((p)->priv_data,i,val)
       #define IP_SENDLINE(p,ln,d,a)   (*(p)->sendLine) ((p)->priv_data,ln,d,a)
       #define IP_DONE(p,err)          (*(p)->done) ((p)->priv_data,err)