<!--
{
  "availability" : [
    "macOS: 13.3.0 -",
    "Xcode: 14.3.0 -"
  ],
  "documentType" : "article",
  "framework" : "Accelerate",
  "identifier" : "/documentation/Accelerate/converting-luminance-and-chrominance-planes-to-an-argb-image",
  "metadataVersion" : "0.1.0",
  "role" : "sampleCode",
  "title" : "Converting luminance and chrominance planes to an ARGB image"
}
-->

# Converting luminance and chrominance planes to an ARGB image

Create a displayable ARGB image using the luminance and chrominance information from your device’s camera.

## Overview

As an alternative to the any-to-any conversion technique that <doc://com.apple.accelerate/documentation/Accelerate/using-vimage-pixel-buffers-to-generate-video-effects> describes, vImage provides low-level functions for creating RGB images from the separate luminance and chrominance planes that an [`AVCaptureSession`](doc://com.apple.documentation/documentation/AVFoundation/AVCaptureSession) instance provides. These functions offer better performance and more granular configuration than using a [`vImageConverter`](/documentation/Accelerate/vImageConverter) instance.

### Configure the YpCbCr-to-ARGB information

The [`vImageConvert_YpCbCrToARGB_GenerateConversion(_:_:_:_:_:_:)`](/documentation/Accelerate/vImageConvert_YpCbCrToARGB_GenerateConversion(_:_:_:_:_:_:)) function
generates the information that vImage requires to convert the luminance and chrominance planes to a single ARGB image.

Video-range YpCbCr formats often don’t use very low and very high values. For example, an 8-bit
video range format typically uses the range `16...235` for luminance and `16...240` for chrominance.
The generate conversion function accepts a [`vImage_YpCbCrPixelRange`](/documentation/Accelerate/vImage_YpCbCrPixelRange) structure that defines the pixel range.

The following code example populates a [`vImage_YpCbCrToARGB`](/documentation/Accelerate/vImage_YpCbCrToARGB) structure with the required conversion information for video-range 8-bit pixels:

```swift
var infoYpCbCrToARGB = vImage_YpCbCrToARGB()

func configureYpCbCrToARGBInfo() {
    var pixelRange = vImage_YpCbCrPixelRange(Yp_bias: 16,
                                             CbCr_bias: 128,
                                             YpRangeMax: 235,
                                             CbCrRangeMax: 240,
                                             YpMax: 235,
                                             YpMin: 16,
                                             CbCrMax: 240,
                                             CbCrMin: 16)

    var ypCbCrToARGBMatrix = vImage_YpCbCrToARGBMatrix(Yp: 1.0,
                                                       Cr_R: 1.402, Cr_G: -0.7141363,
                                                       Cb_G: -0.3441363, Cb_B: 1.772)
    
    _ = vImageConvert_YpCbCrToARGB_GenerateConversion(
        &ypCbCrToARGBMatrix,
        &pixelRange,
        &infoYpCbCrToARGB,
        kvImage422CbYpCrYp8,
        kvImageARGB8888,
        vImage_Flags(kvImageNoFlags))
}
```

### Lock the Core Video pixel buffer

Before the sample app accesses the pixel data that AVFoundation supplies as a [`CVPixelBuffer`](doc://com.apple.documentation/documentation/CoreVideo/cvpixelbuffer-q2e), it calls [`CVPixelBufferLockBaseAddress(_:_:)`](doc://com.apple.documentation/documentation/CoreVideo/CVPixelBufferLockBaseAddress(_:_:)) to lock the pixel buffer and make the underlying memory available.

After the YpCbCr-to-RGB conversion is complete, the code calls [`CVPixelBufferUnlockBaseAddress(_:_:)`](doc://com.apple.documentation/documentation/CoreVideo/CVPixelBufferUnlockBaseAddress(_:_:)) to unlock the pixel buffer.

The `convertYpCbCrToRGB(cvPixelBuffer:)` function performs the YpCbCr-to-RGB conversion.

```swift
CVPixelBufferLockBaseAddress(
    pixelBuffer,
    CVPixelBufferLockFlags.readOnly)

convertYpCbCrToRGB(cvPixelBuffer: pixelBuffer)

CVPixelBufferUnlockBaseAddress(
    pixelBuffer,
    CVPixelBufferLockFlags.readOnly)
```

### Create the source luminance and chrominance pixel buffers

The `convertYpCbCrToRGB(cvPixelBuffer:)` function creates two pixel buffers that share memory with
the [`CVPixelBuffer`](doc://com.apple.documentation/documentation/CoreVideo/cvpixelbuffer-q2e). The Core Video pixel
buffer contains two planes: the plane at index `0` contains one channel that represents the luminance component,
the plane at index `1` contains two interleaved channels that represent the two chrominance components.

The [`init(referencing:planeIndex:overrideSize:pixelFormat:)`](/documentation/Accelerate/vImage/PixelBuffer/init(referencing:planeIndex:overrideSize:pixelFormat:)) function initializes a [`vImage.PixelBuffer`](/documentation/Accelerate/vImage/PixelBuffer) that references a single plane of a multiple-plane Core Video pixel buffer.

```swift
let lumaPixelBuffer = vImage.PixelBuffer(referencing: cvPixelBuffer,
                                         planeIndex: 0,
                                         pixelFormat: vImage.Planar8.self)

let chromaPixelBuffer = vImage.PixelBuffer(referencing: cvPixelBuffer,
                                           planeIndex: 1,
                                           pixelFormat: vImage.Interleaved8x2.self)
```

### Adjust the contrast of the image

The sample app provides a <doc://com.apple.documentation/documentation/SwiftUI/Slider> for changing the contrast of the final image. The following code example uses the tone-mapping
technique that <doc://com.apple.accelerate/documentation/Accelerate/adjusting-saturation-and-applying-tone-mapping> describes:

```swift
if contrast != 1 {
    lumaPixelBuffer.applyGamma(.halfPrecision(contrast),
                               destination: lumaPixelBuffer)
}
```

### Convert the YpCbCr image to an ARGB image

The [`convert(lumaSource:chromaSource:conversionInfo:)`](/documentation/Accelerate/vImage/PixelBuffer/convert(lumaSource:chromaSource:conversionInfo:)) converts the luminance and chrominance information in `lumaPixelBuffer` and `chromaPixelBuffer` to an ARGB image. This pixel buffer method calls the underlying vImage [`vImageConvert_420Yp8_CbCr8ToARGB8888(_:_:_:_:_:_:_:)`](/documentation/Accelerate/vImageConvert_420Yp8_CbCr8ToARGB8888(_:_:_:_:_:_:_:)) function.

```swift
argbPixelBuffer.convert(lumaSource: lumaPixelBuffer,
                        chromaSource: chromaPixelBuffer,
                        conversionInfo: infoYpCbCrToARGB)
```

---

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)