ios - 如何将 CVImageBuffer 转换为 UIImage?

标签 ios swift core-image cvpixelbuffer avcaptureoutput

我有临时变量 tmpPixelBuffer 和像素缓冲区数据,它不是 nil,当检测到元数据对象时,我想从该缓冲区创建图像,所以我可以从该图像裁剪元数据图像。

图像总是nil,我做错了什么?

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {

    tmpPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
}


func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    let image = CIImage(CVPixelBuffer: tmpPixelBuffer)
    let context = CIContext()
    let cgiImage = context.createCGImage(image, fromRect: image.extent())
    let capturedImage = UIImage(CGImage: cgiImage)
    ...
}

我也试过这样做:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    let image = CIImage(CVPixelBuffer: tmpPixelBuffer)
    let context = CIContext(options: nil)

    let cgiImage = context.createCGImage(image, fromRect: CGRect(x: 0, y: 0, width: Int(CVPixelBufferGetWidth(tmpPixelBuffer)), height: Int(CVPixelBufferGetHeight(tmpPixelBuffer))))
    ...
}

但在这种情况下,UIImage 是不可读的。

最佳答案

我将 Andrea 的答案转换为 Swift 3.1:

static func DegreesToRadians(_ degrees: CGFloat) -> CGFloat { return CGFloat( (degrees * .pi) / 180 ) }

static func CreateCGImageFromCVPixelBuffer(pixelBuffer: CVPixelBuffer) -> CGImage? {
    let bitmapInfo: CGBitmapInfo
    let sourcePixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)
    if kCVPixelFormatType_32ARGB == sourcePixelFormat {
        bitmapInfo = [.byteOrder32Big, CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue)]
    } else
    if kCVPixelFormatType_32BGRA == sourcePixelFormat {
        bitmapInfo = [.byteOrder32Little, CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue)]
    } else {
        return nil
    }

    // only uncompressed pixel formats
    let sourceRowBytes = CVPixelBufferGetBytesPerRow(pixelBuffer)
    let width = CVPixelBufferGetWidth(pixelBuffer)
    let height = CVPixelBufferGetHeight(pixelBuffer)
    print("Buffer image size \(width) height \(height)")

    let val: CVReturn = CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
    if  val == kCVReturnSuccess,
        let sourceBaseAddr = CVPixelBufferGetBaseAddress(pixelBuffer),
        let provider = CGDataProvider(dataInfo: nil, data: sourceBaseAddr, size: sourceRowBytes * height, releaseData: {_,_,_ in })
    {
        let colorspace = CGColorSpaceCreateDeviceRGB()
        let image = CGImage(width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: sourceRowBytes,
                        space: colorspace, bitmapInfo: bitmapInfo, provider: provider, decode: nil,
                        shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
        CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
        return image
    } else {
        return nil
    }
}
// utility used by newSquareOverlayedImageForFeatures for
static func CreateCGBitmapContextForSize(_ size: CGSize) -> CGContext? {
    let bitmapBytesPerRow = Int(size.width * 4)
    let colorSpace = CGColorSpaceCreateDeviceRGB()

    guard let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: 8,
                    bytesPerRow: bitmapBytesPerRow, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
    else { return nil }
    context.setAllowsAntialiasing(false)
    return context
}

关于ios - 如何将 CVImageBuffer 转换为 UIImage?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29375471/

相关文章:

iphone - UITableviewCell 中的一个按钮

ios - unwind segue 将数据传递给不同的 View Controller

ios - 如何切换自定义应用内键盘

ios - Core Image 会立即加载图像数据吗?

ios - 将 SAPOData.EntityValue 数组编码/解码到 CompositeStorage

iOS - 无法从其数据源获取单元格

swift - segue中数据丢失(xcode8.0)

ios - Swift 中的 NSLocalizedString 等价物是什么?

ios - CoreImage CIImage 不工作

ios - Swift Barcode Generation,使条码只扫描一次