19.1 Overview

Images are ubiquitous in document formats, and come in a huge variety of formats, ranging from full colour to monochrome, compressed to uncompressed, large to small. The ability to efficiently represent and decode 2d arrays of pixels is vital.

MuPDF represents images using an abstract type, fz_image. This takes the form of a base class, upon which different implementations can be built. All fz_images are reference counted, using the standard fz_keep and fz_drop conventions:

/* 
   fz_drop_image: Drop a reference to an image. 
 
   image: The image to drop a reference to. 
*/ 
void fz_drop_image(fz_context *ctx, fz_image *image); 
 
/* 
   fz_keep_image: Increment the reference count of an image. 
 
   image: The image to take a reference to. 
 
   Returns a pointer to the image. 
*/ 
fz_image *fz_keep_image(fz_context *ctx, fz_image *image);

The key operation required is to be able to request a decoded version of a subarea of that image (yielding a fz_pixmap), suitable for rendering at a given size:

/* 
   fz_get_pixmap_from_image: Called to get a handle to a pixmap from an image. 
 
   image: The image to retrieve a pixmap from. 
 
   subarea: The subarea of the image that we actually care about (or NULL 
   to indicate the whole image). 
 
   trans: Optional, unless subarea is given. If given, then on entry this is 
   the transform that will be applied to the complete image. It should be 
   updated on exit to the transform to apply to the given subarea of the 
   image. This is used to calculate the desired width/height for subsampling. 
 
   w: If non-NULL, a pointer to an int to be updated on exit to the 
   width (in pixels) that the scaled output will cover. 
 
   h: If non-NULL, a pointer to an int to be updated on exit to the 
   height (in pixels) that the scaled output will cover. 
 
   Returns a non NULL pixmap pointer. May throw exceptions. 
*/ 
fz_pixmap *fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *trans, int *w, int *h);

Frequently this will involve decoding the image from its source data, so should be considered a potentially expensive call, both in terms of CPU time, and memory usage.

To minimise the impact of such decodes, fz_images make use of the Store (see chapter 7 Memory Management and The Store) to cache decoded versions in. This means that (subject to enough memory being available) repeated calls to get a fz_pixmap from the same fz_image (with the same parameters) will return the same fz_pixmap each time, with no further decode being required.

The usual reference counting behaviour applies to fz_images, with fz_keep_image and fz_drop_image claiming and releasing references respectively.

Depending on the size at which a fz_image is to be used, it may not be worth decoding it at full resolution; instead, decoding it at a smaller size can save memory (and frequently time). In addition, subsequent rendering operations can often be faster due to having to handle fewer pixels for no quality loss in the final output.

To facilitate this, fz_images will subsample images as appropriate. Subsampling involves an image being decoded to a size an integer power of 2 smaller than their native size. For instance, if an image has a native size of 400x300, and is to be rendered to a final size of 40x30, fz_get_pixmap_from_image may subsample the returned image by up to 8 in each direction, resulting in a 50x37 image.

Subsequent operations (such as smooth scaling and rendering) will proceed much faster due to fewer pixels being involved, and around one sixteenth of the memory will be required.

Many images have a resolution encoded within them. This may or may not be honoured in the way they are positioned on the page, and it will certainly not be honoured when zooming is taken into account, but for some operations it is useful to be able to request it.

/* 
   fz_image_resolution: Request the natural resolution 
   of an image. 
 
   xres, yres: Pointers to ints to be updated with the 
   natural resolution of an image (or a sensible default 
   if not encoded). 
*/ 
void fz_image_resolution(fz_image *image, int *xres, int *yres);

If no resolution is specified within the image, sensible defaults are returned.

A key ability of fz_images is that they are automatically cached in the fz_store when decoded - repeated requests for pixmaps from the same image will (not necessarily) require the image to be decoded again and again.