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)
|