Performing Image Transformation Operations

Image transformation operations alter the values of pixels in an image as defined by custom functions provided as a callback. Unlike convolution operations, transformation functions do not depend on the values of neighboring pixels.

Developers who are interested in efficiently performing gamma corrections or custom pixel manipulation functions on large or real-time image will find these functions useful. With vImage, you can use image transformation operations on the following sorts of functions:

This chapters describes the principles of image transformation and shows you how to use the functions provided by vImage. By reading this chapter you will learn how to:

Transformation Operations

Image transformation functions fall into four categories:

Transformation functions use a vImage_Buffer structure to receive and supply image data. This buffer contains a pointer to image data, the height and width (in pixels) of the image data, and the number of row bytes.

Some transformation functions work in place. That is, the source and destination images can occupy the same memory if they are strictly aligned pixel for pixel. For these, you can provide a pointer to the same vImage_Buffer structure for one of the source images and the destination image.

Gamma Correction

Gamma corrections have to do with changing the intensities of the pixels in an image such that it corrects for the eye’s uneven response to certain colors in an image display. The overall goal of gamma correction is to ensure an accurate depiction of an image given its display’s limited signal range, (such as the number of bits in each pixel).

When vImage performs a gamma correction on an image, it takes each pixel of the source image and passes its intensity through a pre-defined gamma function, and saves this resultant (gamma-corrected) pixel intensity in the destination image.

Using Lookup Tables

You can use a lookup table to apply custom image transformations to an image. By providing an array of 256 integers (for integer pixel types) or 4096 values representing the intensity of floating-point pixel types, you define the destination pixel intensity for each potential source pixel intensity. When vImage transforms an image according to a lookup table, it takes each pixel intensity in the image, indexes into the corresponding array element for that intensity, and saves the intensity stored at that position in the array as the destination pixel intensity.

Listing 7-1 shows how to use a lookup table to apply a custom image transformation.

Listing 7-1  Transforming an image using a lookup table

int MyLookup(void *inData, unsigned int inRowBytes, void *outData, unsigned int outRowBytes, unsigned int height, unsigned int width, void *table, unsigned int table_height, unsigned int table_width, int divisor, vImage_Flags flags )
    vImage_Buffer    in = { inData, height, width, inRowBytes }; // 1
    vImage_Buffer    out = { outData, height, width, outRowBytes }; // 2
    if( table_height != 1 || table_width != 256 ) // 3
        return kvImageInvalidKernelSize;
    return vImageTableLookUp_Planar8(&in, &out, table, flags); // 4
  1. Declares a vImage_Buffer data structure for the source image information. Image data is received as an array of bytes (inData). The other members store the height, width, and bytes-per-row of the image. This data allows vImage to know how large the image data array is, and how to properly handle it.

  2. Declares vImage_Buffer data structure for the destination image information as done previously with the source image.

  3. Checks to make sure that size of the lookup table is suitable for the Planar8 pixel type.

  4. Performs the actual vImage function call and passes up potential errors.

Using Matrix Multiplication

Using matrix multiplication is similar to using a lookup table to determine the destination pixel intensity, except that vImage multiplies each pixel intensity by a specific matrix that you provide. vImage multiplies each pixel intensity by the same matrix to perform this type of transformation. The format of the matrix is a 1D array of 4x4 int16_t data types for integer pixel types, and a 1D array of 4x4 float data types for float pixel types.

vImage provides the following functions for performing pixel-matrix multiplication:

Using Polynomials

You can provide a polynomial function for vImage to apply to each pixel intensity of a given image. You define the polynomial by deciding upon its order, and then providing an array of coefficients (with order - 1 coefficients). You also need to decide the boundary values for separating adjacent ranges of pixel values. This determines how vImage should truncate and/or clip the pixel intensities. You can use polynomials to serve as approximations for other functions that are to expensive to calculate. Imagine a polynomial curve fitting in a data plotting application, except that you are fitting a polynomial to a continuous function rather than a series of discrete data. You can usually create a polynomial with some number of terms that closely matches the function that you want (e.g. sine, power, etc.) over a limited range.

Additionally, vImage supports using piecewise polynomials to transform an image. In order to fit a particular curve over the entire range of possible input pixel values, it is sometimes necessary to use multiple polynomials that fit contiguous subregions of the expected input gamut. For example, if you expect all pixels to be in the range [0, 1.0], you might have one polynomial good for inputs in the range [0, 0.5], and one for [0.5, 1.0]. You may have any number of polynomials, so long as that number is an exact power of two. in order to enforce this requirement, vImage receives this value as the log2segments parameter — the polynomial count. For example, if you say that your function is the head-to-tail concatenation of eight polynomials, the number you should pass in the log2segments parameter should be 3 (because log2(8) = 3).

vImage provides the following functions for using piecewise polynomials to transform images: