将视网膜图像转换为视频:" CGContextScaleCTM:无效的上下文0x0。这是一个严重的错误。"

时间:2016-04-04 23:49:12

标签: ios swift uiimage core-graphics avfoundation

目标是将一组视网膜图像转换为单个视频。

下面的两个函数负责将UIImage写入AVAssetWriterInputPixelBufferAdaptor。他们工作,代码从图像中产生看似有效的视频。

然而,Xcode抱怨这个错误:

  

CGContextScaleCTM:无效的上下文0x0。这是一个严重的错误。这个   应用程序或它使用的库正在使用无效的上下文   从而导致系统稳定性的整体恶化   可靠性。此通知是礼貌的:请解决此问题。它   将在即将到来的更新中成为致命错误。

据推测,它抱怨CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)中的fillPixelBufferFromImage行。但是,删除CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)会导致问题。视网膜图像在视频内部缩小了一半的尺寸(例如,320x568而不是640x1136)。

1)这是一个值得担心的错误吗?其他SO帖子不建议。

2)即使是良性的,你怎么能让这个错误消失?或者将视网膜图像渲染到AVAssetWriterInputPixelBufferAdaptor的正确方法是什么?

func appendPixelBufferForImageAtURL(image: UIImage, pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor, presentationTime: CMTime) -> Bool {
    var appendSucceeded = false

    autoreleasepool {
        if  let pixelBufferPool = pixelBufferAdaptor.pixelBufferPool {
            let pixelBufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)
            let status: CVReturn = CVPixelBufferPoolCreatePixelBuffer(
                kCFAllocatorDefault,
                pixelBufferPool,
                pixelBufferPointer
            )

            if let pixelBuffer = pixelBufferPointer.memory where status == 0 {
                fillPixelBufferFromImage(image, pixelBuffer: pixelBuffer)
                appendSucceeded = pixelBufferAdaptor.appendPixelBuffer(pixelBuffer, withPresentationTime: presentationTime)
                pixelBufferPointer.destroy()
            } else {
                NSLog("Error: Failed to allocate pixel buffer from pool")
            }

            pixelBufferPointer.dealloc(1)
        }
    }

    return appendSucceeded
}


func fillPixelBufferFromImage(image: UIImage, pixelBuffer: CVPixelBufferRef) {
    /// Lock base address
    CVPixelBufferLockBaseAddress(pixelBuffer, 0)

    // Set properties for context
    let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)
    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    let scale = image.scale
    let scaledWidth = image.size.width * scale
    let scaledHeight = image.size.height * scale

    // Create CGBitmapContext
    let context = CGBitmapContextCreate(
        pixelData,
        Int(scaledWidth),
        Int(scaledHeight),
        8,
        CVPixelBufferGetBytesPerRow(pixelBuffer),
        rgbColorSpace,
        CGImageAlphaInfo.PremultipliedFirst.rawValue
    )

    // Set scale for context
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)

    // Draw image into context
    CGContextDrawImage(context, CGRectMake(0, 0, scaledWidth, scaledHeight), image.CGImage)

    /// Unlock base address
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0)
}

1 个答案:

答案 0 :(得分:2)

是的,这是您应该担心的错误。错误消息“这是一个严重的错误”。并且“请解决这个问题”并不是一个玩笑。

这是不正确的:

CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)

因为这些都不是这样的:

  1. 您不在UIView的-drawRect:方法
  2. 您没有致电UIGraphicsBeginImageContext来设置背景
  3. 您没有手动拨打UIGraphicsPushContext
  4. 因此,就UIKit而言,没有“当前”上下文,因此UIGraphicsGetCurrentContext()返回nil。

    您自己创建了位图上下文,因此您应该将比例应用于该上下文:

    CGContextScaleCTM(context, scale, scale)