Swift-技巧(八)CVPixelBuffer To CGImage

摘要

Swift 中圖像的表現形式不只是 Image,還有更加底層的方式,比如 CVPixelBuffer 像素緩存形式,那麼像素緩存轉換爲可以在應用中展示的 CGImage,就要知道有哪些處理了。

CGImage 蘋果官方解釋是一張 bitmap 圖像或者圖像 mask。它是 UIImage 類中的一個屬性,並可以通過 UIImage 的初始化函數稱爲一個 Image 對象。

CVPixelBuffer 是核心緩存像素對象的引用,這裏存儲着一張圖像。

在有些應用場景中,需要把 CVPixelBuffer 轉換爲 CGImage,以便用來展示。

CVPixelBuffer To CGImage

CVPixelBuffer 轉換獲得 CGimage 對象,可以使用 VTCreateCGImageFromCVPixelBuffer(_ pixelBuffer:, options:, imageOut:) -> OSStatus 函數處理,但不是所有的 CVPixelBuffer 對象都可以支持轉換。

public static func create(pixelBuffer: CVPixelBuffer) -> CGImage? {
  var cgImage: CGImage?
  VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage)
  return cgImage
}

在使用以上函數前,要導入框架聲明 VideoToolbox,畢竟不是 UIKit 框架的函數。

import VideoToolbox

除此之外,還可以使用 Core Image 作爲橋樑,間接達轉換效果。這裏要用到 CIImage(cvPixelBuffer:)CIContext 的對象處理。

public static func create(pixelBuffer: CVPixelBuffer, context: CIContext) -> CGImage? {
  let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
  let rect = CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(pixelBuffer),
                                height: CVPixelBufferGetHeight(pixelBuffer))
  return context.createCGImage(ciImage, from: rect)
}

若沒有 context 對象傳入的話,就可以直接自己創建一個 CIContext 對象,這個只是作爲繪圖的畫布,沒有非常高深的地方。

使用這個函數也是需要導入框架 CoreImage

最後一種方式,也能達到轉換的效果,就是使用 CGContext 方法,它可以使用 CVPixelBuffer 對象存儲創建一個 bitmap 的 CGContext 。像素格式可以支持 32ARGB,也可以更改 bitmapInfospace 屬性的變量,達到改變像素格式。這種方式更加靈活,同時也相對來說比較複雜,如果有精力,可以適當瞭解一下。

// 使用之前記得導入框架
import CoreGraphics

public static func create(pixelBuffer: CVPixelBuffer) -> CGImage? {

  guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly) else {
    return nil
  }
  defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly) }

  if let context = CGContext(data: CVPixelBufferGetBaseAddress(pixelBuffer),
                             width: CVPixelBufferGetWidth(pixelBuffer),
                             height: CVPixelBufferGetHeight(pixelBuffer),
                             bitsPerComponent: 8,
                             bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
                             space: CGColorSpaceCreateDeviceRGB(),
                             bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue),
     let cgImage = context.makeImage() {
    return cgImage
  } else {
    return nil
  }
}

代碼中創建 context 對象的初始化函數中的屬性,都是一張圖像中必須要有的信息,若對這感興趣,給我留言,我會詳細說一下圖像。

題外話

時間倉促,說的東西可能不全面,在你查看的過程中遇到什麼問題,評論區給我留言,我會盡快回復

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章