Image I/O
This page describes the mechanism LightWave uses to move images to and from external
files. The mechanism is defined in the lwimageio.h
header file. The LWImageProtocol structure and the pixel type codes are used by the ImageLoader, ImageSaver,
and AnimLoaderHandler classes.
The image protocol is used somewhat differently depending on which direction the image
data is flowing. Loader plug-ins simply call the image protocol functions, but saver
plug-ins provide these functions as callbacks that LightWave calls. Savers fill
in the image protocol structure in their activation functions.
Because of the dual nature of the image protocol structure, there are places in the
definitions where it's convenient to refer to the source and the destination
of an image transfer. For loaders, the source is the plug-in and the destination is
LightWave. For savers, the source is LightWave and the destination is the plug-in.
Image Protocol
Image data is transferred using calls to the functions in an LWImageProtocol. The lwimageio.h
header file defines macros that loaders can use to slightly simplify calls to these
functions. Both the functions and the corresponding macros are listed in the definitions.
typedef struct st_LWImageProtocol {
int type;
void *priv_data;
int (*done) (void *, int);
void (*setSize) (void *, int w, int h);
void (*setParam) (void *, LWImageParam, int, float);
int (*sendLine) (void *, int, const LWPixelID);
void (*setMap) (void *, int, const unsigned char[3]);
} LWImageProtocol, *LWImageProtocolID;
- type
- The pixel type code, described below. This identifies the kind of data that will be sent
in sendLine.
priv_data
- The first argument to the protocol functions. This is a pointer to data owned by the
destination. Loaders just need to pass this along to the protocol functions (the macros
hide this from you). Savers set this field to point to anything they like, typically a
structure that holds data needed to process the save.
result = done( priv_data, error )
result = LWIP_DONE( protocol, error )
- Called when there's no more image data to send. The incoming error code and the outgoing
result can be any of the result codes defined below.
setSize( priv_data, width, height )
LWIP_SETSIZE( protocol, width, height )
- Set the pixel dimensions of the image. The width and height are the number of pixels in
a scanline and the number of scanlines, respectively. This is called before the first call
to sendLine.
setParam( priv_data, paramid, intparam, floatparam )
LWIP_SETPARAM( protocol, paramid, intparam, floatparam )
- Set other image parameters. In most cases, only one of the two parameter arguments will
be used, while the other should be set to 0 by sources and ignored by destinations. The
parameter ID can be one of the following.
LWIMPAR_ASPECT (float)
- The pixel aspect ratio, defined as width/height. This will most often be 1.0 (square
pixels, the default), but D1 NTSC images, for example, use a pixel aspect of 0.9, meaning
that each pixel is 0.9 times as wide as it is high.
- LWIMPAR_NUMCOLS (int)
- The number of entries in the color table of an indexed-color image (an image of type LWIMTYP_INDEX8).
Valid values are between 2 and 256.
- LWIMPAR_PIXELWIDTH (float)
- The physical size of a pixel in millimeters. Savers can combine this with the pixel
aspect to record a DPI setting for file formats that support it.
- LWIMPAR_FRAMESPERSECOND (float)
- The playback rate in frames per second.
- LWIMPAR_BLACKPOINT (float)
- The black point of the image. The black point and white point define a nominal minimum
and maximum intensity for an image. These are used, for example, when displaying the image
on a device with limited dynamic range.
- LWIMPAR_WHITEPOINT (float)
- The white point of the image.
- LWIMPAR_GAMMA (float)
- The nonlinearity of the intensity encoding in the image.
The only parameter that loaders are required to set is the LWIMPAR_NUMCOLS
value for LWIMTYP_INDEX8 images.
- result = sendLine( priv_data, y, scanline_pixels )
result = LWIP_SENDLINE( protocol, y, scanline_pixels )
- Send one scanline from the image. Loaders must call setSize before the first
call to sendLine. Scanlines are numbered from the top of the image, starting at
0. Loaders don't
have to send scanlines in a particular order, but savers will receive scanlines in top to
bottom
order (or bottom to top if they specified the IMGF_REVERSE flag in their sendData
call). A scanline begins with the leftmost pixel. The structure of the pixel data depends
on the pixel type. Returns IPSTAT_OK or an error code.
setMap( priv_data, index, rgb )
LWIP_SETMAP( protocol, index, rgb )
- Set the color of an entry in the color table of an indexed-color image. Loaders need to
call setParam with a LWIMPAR_NUMCOLS parameter before calling setMap
for the first time, but setMap may be called any time after that and before the
first sendLine. The index identifies the color table entry, which is numbered
from 0 to numcolors-1.
Pixel Data
The structure of the data in a scanline will vary, depending on the pixel type. Each
scanline is an array of either unsigned bytes or floats. Bytes can contain any unsigned
value between 0 and 255. The nominal range for float values is 0.0 to 1.0, but values
outside that range may also appear.
Each pixel's data is contiguous--the scanline contains all of the channel values for
the first pixel, followed by the values for the second, and so on. The lwimageio.h
header file defines structures for many of the pixel types. You can use these to cast the void
* argument in sendLine to a pointer of the appropriate type for the pixel
data.
For each pixel type, the data is organized as follows.
- LWIMTYP_RGB24
- Each scanline is an array of unsigned char in RGBRGB... order. The
corresponding typedef is LWPixelRGB24.
- LWIMTYP_GREY8
- Each scanline is an array of unsigned char, with one byte per grayscale pixel.
- LWIMTYP_INDEX8
- Each scanline is an array of unsigned char, with one byte per pixel containing
color map indexes.
- LWIMTYP_GREYFP
- Each scanline is an array of float, with one float per pixel.
- LWIMTYP_RGBFP
- Each scanline is an array of float in RGBRGB... order. The
corresponding typedef is LWPixelRGBFP.
- LWIMTYP_RGBA32
- Each scanline is an array of unsigned char in RGBARGBA... order and
contains both RGB color and alpha channel values. The corresponding typedef is LWPixelRGBA32.
- LWIMTYP_RGBAFP
- Each scanline is an array of float in RGBARGBA... order and contains
both RGB color and alpha channel values. The corresponding typedef is LWPixelRGBAFP.
Error Handling
There are two ways that sources and destinations can notify each other of an error. The
destination can return error codes from the sendLine and done functions,
and the source can pass an error code to the destination's done function.
If a loader encounters an error while reading a file, it should stop sending data to
LightWave and call done, setting the error argument to IPSTAT_FAILED. If
a saver's done callback is called with a non-zero error argument, the saver
should perform whatever cleanup it thinks is appropriate, which may include removing the
partially saved file, and return the same error code from done.
If a saver encounters an error while writing a file, it should return IPSTAT_FAILED
from its sendLine and done callbacks. Note that the first sendLine
call is a saver's first opportunity to signal an error to LightWave, so its callbacks will
continue to be called after the error is detected and until sendLine is called.
It's a good idea for savers to include an error field in their priv_data so that their
callbacks can respond appropriately until LightWave can be told that something's gone
wrong.
Example
See the ancounter animation loader and the iff image loader and saver samples. |