<!--
{
  "documentType" : "article",
  "framework" : "Accelerate",
  "identifier" : "/documentation/Accelerate/building-a-basic-image-processing-workflow",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Building a Basic Image-Processing Workflow"
}
-->

# Building a Basic Image-Processing Workflow

Resize an image with vImage.

## Discussion

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`](/documentation/Accelerate/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:

![Photos showing the original image and the resized image.](images/com.apple.accelerate/media-2953430@2x.png)

### Initialize an Image Format and vImage Buffers

To learn about initializing the buffers you’ll need to perform a scaling operation, see <doc://com.apple.documentation/documentation/Accelerate/converting-bitmap-data-between-core-graphics-images-and-vimage-buffers> and <doc://com.apple.documentation/documentation/Accelerate/creating-and-populating-buffers-from-core-graphics-images>. In this example, you’ll need the image format and buffers discussed in <doc://com.apple.documentation/documentation/Accelerate/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.

```swift
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`](/documentation/Accelerate/vImage_CGImageFormat/bitmapInfo) value with <doc://com.apple.documentation/documentation/CoreGraphics/CGImageAlphaInfo/premultipliedFirst> or <doc://com.apple.documentation/documentation/CoreGraphics/CGImageAlphaInfo/premultipliedLast>), before you apply the scale operation, see <doc://com.apple.documentation/documentation/Accelerate/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(_:_:_:_:)`](/documentation/Accelerate/vImageScale_ARGB8888(_:_:_:_:)) function. This function works equally well on all channel orderings; for example, RGBA or BGRA.

```swift
error = vImageScale_ARGB8888(&sourceBuffer,
                             &destinationBuffer,
                             nil,
                             vImage_Flags(kvImageHighQualityResampling))
        
guard error == kvImageNoError else {
    fatalError("Error in vImageScale_ARGB8888: \(error)")
}
```

The [`kvImageHighQualityResampling`](/documentation/Accelerate/kvImageHighQualityResampling) flag uses a high-quality Lanczos 5 x 5 resampling filter. If you require faster scaling, pass [`kvImageNoFlags`](/documentation/Accelerate/kvImageNoFlags).

`destinationBuffer` now contains the scaled version of `sourceBuffer`. To learn how to display the scaled result to your user, see <doc://com.apple.documentation/documentation/Accelerate/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:

```swift
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:

```swift
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))
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)