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:


\begin{lstlisting}
/*
fz_drop_image: Drop a reference to an image.
\par
image: ...
....
*/
fz_image *fz_keep_image(fz_context *ctx, fz_image *image);
\end{lstlisting}

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:


\begin{lstlisting}
/*
fz_get_pixmap_from_image: Called to get a handle to a pix...
...ge, const fz_irect *subarea, fz_matrix *trans, int *w, int *h);
\end{lstlisting}

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


\begin{lstlisting}
/*
fz_image_resolution: Request the natural resolution
of a...
...oid fz_image_resolution(fz_image *image, int *xres, int *yres);
\end{lstlisting}

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.