19.4 Implementing an Image Type

Should it be necessary, support for new types of image can be implemented fairly simply, by defining a structure derived from a fz_image. Perhaps:

typedef struct 
{ 
   fz_image super; 
   <foo specific fields> 
} foo_image;

Then we’d define a new image creation function, fz_new_image_from_foo, of the form:

fz_image *fz_new_image_from_foo(fz_context *ctx, <foo specific parameters>) { 
   foo_image *foo = fz_new_image(ctx, ..., foo_image, foo_get, foo_size, foo_drop); 
   if (!foo) 
      return NULL; 
 
   <initialise foo specific fields from foo specific parameters> 
 
   return &foo->super; 
}

The key call here is the call to fz_new_image. This is a macro which wraps a call to fz_new_image_of_size:

/* 
   fz_new_image_of_size: Internal function to make a new fz_image 
   structure for a derived class. 
 
   w,h: Width and height of the created image. 
 
   bpc: Bits per component. 
 
   colorspace: The colorspace (determines the number of components, 
   and any color conversions required while decoding). 
 
   xres, yres: The X and Y resolutions respectively. 
 
   interpolate: 1 if interpolation should be used when decoding 
   this image, 0 otherwise. 
 
   imagemask: 1 if this is an imagemask (i.e. transparent), 0 
   otherwise. 
 
   decode: NULL, or a pointer to to a decode array. The default 
   decode array is [0 1] (repeated n times, for n color components). 
 
   colorkey: NULL, or a pointer to a colorkey array. The default 
   colorkey array is [0 255] (repeatd n times, for n color 
   components). 
 
   mask: NULL, or another image to use as a mask for this one. 
   A new reference is taken to this image. Supplying a masked 
   image as a mask to another image is illegal! 
 
   size: The size of the required allocated structure (the size of 
   the derived structure). 
 
   get: The function to be called to obtain a decoded pixmap. 
 
   get_size: The function to be called to return the storage size 
   used by this image. 
 
   drop: The function to be called to dispose of this image once 
   the last reference is dropped. 
 
   Returns a pointer to an allocated structure of the required size, 
   with the first sizeof(fz_image) bytes initialised as appropriate 
   given the supplied parameters, and the other bytes set to zero. 
*/ 
fz_image *fz_new_image_of_size(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace, int xres, int yres, int interpolate, int imagemask, float *decode, int *colorkey, fz_image *mask, int size, fz_image_get_pixmap_fn *get, fz_image_get_size_fn *get_size, fz_drop_image_fn *drop); 
 
#define fz_new_image(CTX,W,H,B,CS,X,Y,I,IM,D,C,M,T,G,S,Z) \ 
((T*)Memento_label(fz_new_image_of_size(CTX,W,H,B,CS,X,Y,I,IM,D,C,M,sizeof(T),G,S,Z),#T))

The macro takes identical parameters to the function other than passing the structure type in place of the structure type saved, and performing a typecast to simplify the typical enclosing code.

Both function and macro take pointers to 3 functions that need to be defined for the new format. Firstly, foo_get is of the following type:

/* 
   fz_get_pixmap_fn: Function type to get a decoded pixmap 
   for an image. 
 
   im: The image to decode. 
 
   subarea: NULL, or the subarea of the image required. Expressed 
   in terms of a rectangle in the original width/height of the 
   image. If non NULL, this should be updated by the function to 
   the actual subarea decoded - which must include the requested 
   area! 
 
   w, h: The actual width and height that the whole image would 
   need to be decoded to. 
 
   l2factor: On entry, the log 2 subsample factor required. If 
   possible the decode process can take care of (all or some) of 
   this subsampling, and must then update the value so the caller 
   knows what remains to be done. 
 
   Returns a reference to a decoded pixmap that satisfies the 
   requirements of the request. 
*/ 
typedef fz_pixmap *(fz_image_get_pixmap_fn)(fz_context *ctx, fz_image *im, fz_irect *subarea, int w, int h, int *l2factor);

Secondly, foo_get_size will be of type:

/* 
   fz_image_get_size_fn: Function type to get the given storage 
   size for an image. 
 
   Returns the size in bytes used for a given image. 
*/ 
typedef size_t (fz_image_get_size_fn)(fz_context *, fz_image *);

Finally, foo_drop will be of type:

/* 
   fz_drop_image_fn: Function type to destroy an images data 
   when its reference count reaches zero. 
*/ 
typedef void (fz_drop_image_fn)(fz_context *ctx, fz_image *image);

The actual deallocation of the fz_image block and its associated resources will be done on return from this function. The fz_drop_image_fn is responsible just for deallocating its implementation specific resources (i.e. the contents of foo_image rather than fz_image).