---
title: Building a Basic Image-Processing Workflow
framework: accelerate
role: article
role_heading: Article
path: accelerate/building-a-basic-image-processing-workflow
---

# Building a Basic Image-Processing Workflow

Resize an image with vImage.

## Overview

Overview vImage provides fast and accurate high-level functions for image manipulation; for example, compositing, convolution, and histogram operations. It operates on common image formats through vImage_Buffer structures. vImage buffers describe the size of an image and the number of bytes in each row, and point to the image pixel data. Buffers are initialized from Core Graphics images, Core Video pixel buffers, or raw pixel data. The pixel data a buffer points to can be used to create a new Core Graphics image or can be copied into a Core Video pixel buffer. In the simplest workflow, you convert an image to a vImage buffer, apply an operation to the buffer, and convert the buffer back to an image. In this example, the width and height of the result are one-third of the original:

Initialize an Image Format and vImage Buffers To learn about initializing the buffers you’ll need to perform a scaling operation, see Converting bitmap data between Core Graphics images and vImage buffers and Creating and Populating Buffers from Core Graphics Images. In this example, you’ll need the image format and buffers discussed in Creating and Populating Buffers from Core Graphics Images. However, you’ll use the following code to initialize a destination buffer with a height and width that are a quarter of the source dimensions. let destinationHeight = Int(CGFloat(sourceBuffer.height) * 0.25) let destinationWidth = Int(CGFloat(sourceBuffer.width) * 0.25)

guard var destinationBuffer = try? vImage_Buffer(width: destinationWidth,                                                  height: destinationHeight,                                                  bitsPerPixel: format.bitsPerPixel) else {                                                     return nil }

defer {     destinationBuffer.free() } Apply the Scale Operation If you’re rescaling an image with premultiplied alpha (that is, with a bitmapInfo value with CGImageAlphaInfo.premultipliedFirst or CGImageAlphaInfo.premultipliedLast), before you apply the scale operation, see Building a Basic Image-Processing Workflow. Otherwise, with the source and destination buffers properly initialized, you’re ready to perform the scaling operation. Because your format contains four 8-bit channels, you use the vImageScale_ARGB8888(_:_:_:_:) function. This function works equally well on all channel orderings; for example, RGBA or BGRA. error = vImageScale_ARGB8888(&sourceBuffer,                              &destinationBuffer,                              nil,                              vImage_Flags(kvImageHighQualityResampling))          guard error == kvImageNoError else {     fatalError("Error in vImageScale_ARGB8888: \(error)") } The kvImageHighQualityResampling flag uses a high-quality Lanczos 5 x 5 resampling filter. If you require faster scaling, pass kvImageNoFlags. destinationBuffer now contains the scaled version of sourceBuffer. To learn how to display the scaled result to your user, see Creating a Core Graphics Image from a vImage Buffer. After you’ve finished with the source and destination buffers, it’s important that you free the memory allocated to them: sourceBuffer.free() destinationBuffer.free() Avoid Artifacts by Unpremultiplying If you’re rescaling an image with premultiplied alpha, you may see artifacts in high-frequency regions of the image. To avoid this situation, unpremultiply the image data — that is, remove the premultiplied alpha value from the image data — before the scaling operation, and premultiply the scaled result. This code shows the additional operations required, with error handling removed for brevity: error = vImageUnpremultiplyData_ARGB8888(&sourceBuffer,                                          &sourceBuffer,                                          vImage_Flags(kvImageNoFlags))   error = vImageScale_ARGB8888(&sourceBuffer,                              &destinationBuffer,                              nil,                              vImage_Flags(kvImageHighQualityResampling))   error = vImagePremultiplyData_ARGB8888(&destinationBuffer,                                        &destinationBuffer,                                        vImage_Flags(kvImageNoFlags))

## See Also

### Image Processing Essentials

- [Converting bitmap data between Core Graphics images and vImage buffers](accelerate/converting-bitmap-data-between-core-graphics-images-and-vimage-buffers.md)
- [Creating and Populating Buffers from Core Graphics Images](accelerate/creating-and-populating-buffers-from-core-graphics-images.md)
- [Creating a Core Graphics Image from a vImage Buffer](accelerate/creating-a-core-graphics-image-from-a-vimage-buffer.md)
- [Applying geometric transforms to images](accelerate/applying-geometric-transforms-to-images.md)
- [Compositing images with alpha blending](accelerate/compositing-images-with-alpha-blending.md)
- [Compositing images with vImage blend modes](accelerate/compositing-images-with-vimage-blend-modes.md)
- [Applying vImage operations to regions of interest](accelerate/applying-vimage-operations-to-regions-of-interest.md)
- [Optimizing image-processing performance](accelerate/optimizing-image-processing-performance.md)
- [vImage](accelerate/vimage-library.md)
