Swift skill CGImage To CVPixelBuffer

abstract

The Image representation in iOS is not only Image, but also a more underlying way, such as CVPixelBuffer pixel cache. The way that CGImage can be converted to pixel cache also needs to be understood.

CGImage Apple's official explanation is a bitmap Image or Image mask. It is an attribute in the UIImage class and can be called an Image object through the initialization function of UIImage.

CVPixelBuffer is the reference of the core cache pixel object, where an image is stored.

In application scenarios where CVPixelBuffer objects are required, CGImage can be converted to.

CGImage To CVPixelBuffer

Here, the functions in the CGContext object are used to convert CGImage to CVPixelBuffer. You need to import the CoreGraphics framework in advance.

import CoreGraphics

Then put the conversion function in the CGImage extension, you can directly access the width and height of the CGImage object, and even access itself through self.

extension CGImage {
	// Conversion function
	...
}

Implementation method

Next, process CGImage to CVPixelBuffer from less to more as required. The first is to directly obtain an ARGB pixel cache object.

public func pixelBuffer() -> CVPixelBuffer? {
	return pixelBuffer(width: width, height: height, orientation: .up)
}

The width and height in the function can be accessed directly. orientation is the direction of the image. Here, the default is. up (vertical).

Then you can adjust the width and height of the picture and convert it into an ARGB pixel cache object.

public func pixelBuffer(width: Int, height: Int,
                        orientation: CGImagePropertyOrientation) -> CVPixelBuffer? {
  return pixelBuffer(width: width, height: height,
                     pixelFormatType: kCVPixelFormatType_32ARGB,
                     colorSpace: CGColorSpaceCreateDeviceRGB(),
                     alphaInfo: .noneSkipFirst,
                     orientation: orientation)
}

Some parameters are added to the function. pixelFormatType is the pixel format type. ARGB format is set here, colorSpace is the color space parameter, and alphaInfo is the location of alpha in memory. If these parameters are uncertain, they can be set directly.

This function can set so many parameters. From another point of view, this function is the final implementation. The above functions encapsulate this function.

The logic of this function is to create and configure the CGContext object, and then call its draw function to get the CBPixelBuffer object. If you are interested in the meaning of these parameters, how to configure them and what extensions can be made, leave me a message.

public func pixelBuffer(width: Int, height: Int,
                          pixelFormatType: OSType,
                          colorSpace: CGColorSpace,
                          alphaInfo: CGImageAlphaInfo,
                          orientation: CGImagePropertyOrientation) -> CVPixelBuffer? {
    assert(orientation == .up)

    var maybePixelBuffer: CVPixelBuffer?
    let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
                 kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
    let status = CVPixelBufferCreate(kCFAllocatorDefault,
                                     width,
                                     height,
                                     pixelFormatType,
                                     attrs as CFDictionary,
                                     &maybePixelBuffer)

    guard status == kCVReturnSuccess, let pixelBuffer = maybePixelBuffer else {
      return nil
    }

    let flags = CVPixelBufferLockFlags(rawValue: 0)
    guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(pixelBuffer, flags) else {
      return nil
    }
    defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, flags) }

    guard let context = CGContext(data: CVPixelBufferGetBaseAddress(pixelBuffer),
                                  width: width,
                                  height: height,
                                  bitsPerComponent: 8,
                                  bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
                                  space: colorSpace,
                                  bitmapInfo: alphaInfo.rawValue)
    else {
      return nil
    }

    context.draw(self, in: CGRect(x: 0, y: 0, width: width, height: height))
    return pixelBuffer
  }

Digression

In a hurry, what you said may not be comprehensive. If you encounter any problems in the process of viewing, leave me a message in the comment area and I will reply as soon as possible.

Tags: Swift

Posted on Tue, 30 Nov 2021 09:37:10 -0500 by hillbilly928