【问题标题】:Convert a CMSampleBuffer into a UIImage将 CMSampleBuffer 转换为 UIImage
【发布时间】:2015-01-15 12:00:22
【问题描述】:

这是一个将 CMSampleBuffer 转换为 UIImage 的函数(来自 Apple 文档的代码)

func imageFromSampleBuffer(sampleBuffer: CMSampleBuffer) -> UIImage {
    // Get a CMSampleBuffer's Core Video image buffer for the media data
    var imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    // Lock the base address of the pixel buffer
    CVPixelBufferLockBaseAddress(imageBuffer, 0)

    // Get the number of bytes per row for the pixel buffer
    var baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)

    // Get the number of bytes per row for the pixel buffer
    var bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
    // Get the pixel buffer width and height
    var width = CVPixelBufferGetWidth(imageBuffer)
    var height = CVPixelBufferGetHeight(imageBuffer)

    // Create a device-dependent RGB color space
    var colorSpace = CGColorSpaceCreateDeviceRGB()

    // Create a bitmap graphics context with the sample buffer data
    let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.NoneSkipLast.rawValue)
    var context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo)
    // Create a Quartz image from the pixel data in the bitmap graphics context
    var quartzImage = CGBitmapContextCreateImage(context);
    // Unlock the pixel buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    // Create an image object from the Quartz image
    var image = UIImage(CGImage: quartzImage)!

    return image
}

当我尝试使用 UIImageView 可视化 UIImage 时,我什么也得不到。
有什么想法吗?

【问题讨论】:

  • Xcode 输出中是否出现错误?

标签: ios swift uiimage avcapturesession cmsamplebufferref


【解决方案1】:

我刚刚在我当前的项目中完成了完全相同的功能,这就是我如何让它工作的(通过大量的谷歌搜索和一些试验和错误):

let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.NoneSkipFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue)

另外,请确保您在主线程中呈现 UIImageView(您可能在相机会话线程中获取 CMSampleBuffer),因为 UIKit 只能在主线程中执行。否则,您将不得不等待很长时间才能显示图像。

【讨论】:

  • bitmapInfo 获取 UIImage 的最佳做法是什么?
【解决方案2】:

@Zigglzworth 需要为 captureVideoDataOutput 设置 kCVPixelFormatType_32BGRA

        let videoOutput = AVCaptureVideoDataOutput()
        videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA]

【讨论】:

    【解决方案3】:

    这是 Swift 3.0 的解决方案,其中扩展了 CMSampleBuffer,创建一个变量,为您提供可选的 UIImage

    import AVFoundation
    
    extension CMSampleBuffer {
        var uiImage: UIImage? {
            guard let imageBuffer = CMSampleBufferGetImageBuffer(self) else { return nil }
    
            CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
            let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
            let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
            let width = CVPixelBufferGetWidth(imageBuffer)
            let height = CVPixelBufferGetHeight(imageBuffer)
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)
            guard let context = CGContext(data: baseAddress,
                                          width: width,
                                          height: height,
                                          bitsPerComponent: 8,
                                          bytesPerRow: bytesPerRow,
                                          space: colorSpace,
                                          bitmapInfo: bitmapInfo.rawValue) else { return nil }
            guard let cgImage = context.makeImage() else { return nil }
    
            CVPixelBufferUnlockBaseAddress(imageBuffer,CVPixelBufferLockFlags(rawValue: 0));
    
            return UIImage(cgImage: cgImage)
        }
    }
    

    【讨论】:

    • 我得到::CGBitmapContextCreate:无效数据字节/行:对于 8 个整数位/组件、3 个组件、kCGImageAlphaNoneSkipFirst,应该至少为 5120
    • @Zigglzworth 你可能有一张灰度图像。您可以相应地调整这些值。
    • 嗯不是这样.. 不知道为什么这对我不起作用
    • 你有机会把图片贴在某个地方吗?
    • @CodeBender 非常感谢 :)
    猜你喜欢
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2013-03-21
    相关资源
    最近更新 更多