5.7 Tuning

Some of MuPDF’s functionality relies on heuristics to make decisions. Rather than hard code these decisions in the library code, the tuning context allows callers to override the defaults with their own ‘tuned’ versions.

Currently, we have just 2 calls defined here, both to do with image handling, but this may expand in future.

The first tuning function enables fine control over how much of an image MuPDF should decode if it only requires a subarea:

/* 
   fz_tune_image_decode_fn: Given the width and height of an image, 
   the subsample factor, and the subarea of the image actually 
   required, the caller can decide whether to decode the whole image 
   or just a subarea. 
 
   arg: The caller supplied opaque argument. 
 
   w, h: The width/height of the complete image. 
 
   l2factor: The log2 factor for subsampling (i.e. image will be 
   decoded to (w>>l2factor, h>>l2factor)). 
 
   subarea: The actual subarea required for the current operation. 
   The tuning function is allowed to increase this in size if required. 
*/ 
typedef void (fz_tune_image_decode_fn)(void *arg, int w, int h, int l2factor, fz_irect *subarea);

The purpose of allowing larger areas to be decoded than are immediately required, is so that these larger areas can be placed into the cache. This may mean that future requests can be satisfied from the cache rather than requiring complete new decodes. An example of such a situation might be where MuPDF is powering a viewer application, and a page is slowly panned onto screen revealing more and more of an image. These tuning functions put control over such decisions back into the hands of the application author.

Having defined a function of this type to implement the desired strategy, it can be set into the context using:

/* 
   fz_tune_image_decode: Set the tuning function to use for 
   image decode. 
 
   image_decode: Function to use. 
 
   arg: Opaque argument to be passed to tuning function. 
*/ 
void fz_tune_image_decode(fz_context *ctx, fz_tune_image_decode_fn *image_decode, void *arg);

The second function allows fine control over the scaling used when images are scaled:

/* 
   fz_tune_image_scale_fn: Given the source width and height of 
   image, together with the actual required width and height, 
   decide whether we should use mitchell scaling. 
 
   arg: The caller supplied opaque argument. 
 
   dst_w, dst_h: The actual width/height required on the target device. 
 
   src_w, src_h: The source width/height of the image. 
 
   Return 0 not to use the Mitchell scaler, 1 to use the Mitchell 
   scaler. All other values reserved. 
*/ 
typedef int (fz_tune_image_scale_fn)(void *arg, int dst_w, int dst_h, int src_w, int src_h);

Essentially this routine allows the application author to exercise control over whether images are displayed with interpolation or not. Rather than simple linear interpolation, MuPDF uses the ‘Mitchell’ sampling function. This provides subjectively better quality.

The default is to use the Mitchell scaler only when downscaling, to avoid details ‘dropping out’ of images, but by providing a tuning function, the application author can choose to use it in more (or fewer) cases as desired.

Having defined a function of this type to implement the desired strategy, it can be set into the context using:

/* 
   fz_tune_image_scale: Set the tuning function to use for 
   image scaling. 
 
   image_scale: Function to use. 
 
   arg: Opaque argument to be passed to tuning function. 
*/ 
void fz_tune_image_scale(fz_context *ctx, fz_tune_image_scale_fn *image_scale, void *arg);