- iOS 13.0+
- Xcode 11.0+
This sample code project uses the vImage piecewise gamma function to adjust the response curve (that is, the value of an output pixel based on the value of the corresponding input pixel) of an 8-bit ARGB image. Changing the shape of the response curve changes the brightness and contrast of an image.
A piecewise gamma function allows you to apply a either linear or exponential response curve to pixels in an image based their value.
This app displays a sample image and uses a segmented control to apply different preset linear (labelled L1 to L4) and exponential (labelled E1 to E3) response curves. In this sample, you’ll learn how different response curves affect an image by changing its brightness and contrast.
Define Response Curve Presets
This sample app defines a structure,
Response, that contains the coefficients used by the linear function, the gamma used by the exponential function, and the boundary between the linear and exponential functions:
presets array contains sample presets that apply different adjustments to the sample image.
When the user changes the selected segment of the segmented control, the appropriate
preset structure is passed to
get which applies the adjustment to the image and displays the result.
Define the Adjustment Parameters
You specify the division between linear and gamma adjustments by passing a boundary parameter to the piecewise gamma function,
v. The function uses the gamma curve to calculate the output value when the input value is greater than or equal to the boundary value. Otherwise, the function uses the linear curve.
For 8-bit images, the boundary is a
Pixel value, so a value of
0 indicates all pixels are gamma adjusted, a value of
255 indicates all pixels are linearly adjusted, and a value of
127 indicates all pixels with a value less than one-half are linearly adjusted.
You pass the linear and exponential coefficients (for example, the
(a * inputvalue) + b) as arrays of floating-point values:
Remove the Alpha Channel
v function used in this sample treats the interleaved RGBA buffer as a single plane, applying the same gamma adjustment to all channels—including the alpha channel. Adjusting the response curve of the alpha channel changes transparency properties. To avoid this, convert the RGBA source image to RGB and apply the adjustment to that.
Create the RGB version of the source image by creating a 3-channel, 8-bit format:
Create a 3-channel destination buffer using the source buffer’s dimensions and the RGB format’s
v to populate the destination with only the color channels:
destination contains the red, green, and blue channels of
Prepare the Buffers
v function expects planar buffers. Create a planar representation of the RGB buffer that is three times its width to pass to the piecewise gamma function:
This approach applies the same adjustment to all three channels of your interleaved buffer. If you need to separate the interleaved buffer to individual planar buffers (for example, to adjust individual colors with different parameters), see Optimizing Image Processing Performance.
Apply the Adjustment
With the parameters and buffers prepared, call
v to apply the adjustment. Because the piecewise gamma function can work in place, you can use
planar as the source and destination:
To create the image, pass the destination buffer and RGB format to
The following explains the presets in more detail:
Apply Linear Adjustment
The following presets use the linear adjustment (that is,
boundary is 255). The output value for each pixel is calculated as:
L1 preset returns each pixel unchanged:
L2 preset returns a washed out image where blacks are transformed to grays. When the input value is
0, the output value is
L3 preset returns a an image with a lot of contrast. When the input value is less than one-third, the output value is
0; when the input value is greater than two-thirds, the output value is
L4 preset returns a negative version of the image. When the input value is
1, the output value is
0; when the input value is
0, the output value is
Apply Exponential Adjustment
The following presets use the exponential adjustment (that is,
boundary is 0). The output value for each pixel is calculated as:
In these examples,
exponential is defined as
[1, 0, 0] and the calculation can be simplified to
E1 preset returns each pixel unchanged:
E2 preset has an overall darkening effect:
E3 preset has an overall lightening effect:
Correct Gamma Before Applying Operations
Many vImage operations—such as convolution and scaling—provide optimal results when working on images with a linear response curve. If you are working with nonlinear images—such as sRGB—consider converting them to a linear color space by applying a reciprocal gamma (such as
1/2), performing the operation, and converting them back to their original domain by applying the original gamma (such as