Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Abstract

The representation form of images in Swift is not only Image, but also a more low-level way, such as CVPixelBuffer pixel cache form, so the way that CGImage can be converted into pixel cache also needs to be understood.

CGImage is a bitmap image or image mask. It is a property in the UIImage class and can be called an Image object by UIImage’s initialization function.

CVPixelBuffer is a reference to the core cache pixel object where an image is stored.

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

CGImage To CVPixelBuffer

The CGImage is converted to CVPixelBuffer using the function in the CGContext object. The CoreGraphics framework needs to be imported in advance.

import CoreGraphics
Copy the code

We then place the conversion function in the CGImage extension, which can access the width, height, and even self of the CGImage object directly.

Extension CGImage {// Transform function... }Copy the code

Implementation method

The CGImage to CVPixelBuffer is then processed as needed in order of less to more. The first is to get an ARGB pixel cache object directly.

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

The width and height of the function can be accessed directly, and orientation is the orientation of the image, which is.up by default.

You can then adjust the width and height of the image to 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)
}
Copy the code

PixelFormatType is the pixelFormatType, which is ARGB, colorSpace is the colorSpace parameter, and alphaInfo is the location of alpha in memory. If you are not sure, set these parameters to this.

This function can set so many parameters, from another point of view, this function is the final implementation, the above several functions are the encapsulation of this function.

The processing logic for this function is to create and configure the CGContext object, and then call its draw function to get the CBPixelBuffer object. If you’re interested in what these parameters mean, how to configure them, and what other extensions can be made, leave me a comment.

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
  }
Copy the code

digression

Time is short and what you said may not be comprehensive. If you have any problems during your review, please leave a message in the comment section and I will reply as soon as possible