• 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,  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),
                                  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 对象的初始化函数中的属性,都是一张图像中必须要有的信息,若对这感兴趣,给我留言,我会详细说一下图像。

    题外话

    时间仓促,说的东西可能不全面,在你查看的过程中遇到什么问题,评论区给我留言,我会尽快回复

  • 相关阅读:
    ZOJ2587 Unique Attack(判定最小割唯一性)
    SPOJ371 Boxes(最小费用最大流)
    SGU185 Two shortest(最小费用最大流/最大流)
    POJ2112 Optimal Milking(最大流)
    HDU3996 Gold Mine(最大权闭合子图)
    POJ3680 Intervals(最小费用最大流)
    SPOJ 7258 Lexicographical Substring Search(后缀自动机)
    HDU 4436 str2int(后缀自动机)
    SPOJ 1812 Longest Common Substring II(后缀自动机)
    CodeForces 235C Cyclical Quest(后缀自动机)
  • 原文地址:https://www.cnblogs.com/shsuper/p/15604728.html
Copyright © 2020-2023  润新知