将视网膜图像转换为视频:"CGContextScaleCTM: invalid context 0x0. This is a serious error."
Turning retina images into video: "CGContextScaleCTM: invalid context 0x0. This is a serious error."
目标是将一系列视网膜图像转换为单个视频。
下面的两个函数负责将一个UIImage写入一个AVAssetWriterInputPixelBufferAdaptor。它们起作用了,并且代码从图像中生成了看似有效的视频。
然而,Xcode 抱怨这个错误:
CGContextScaleCTM: invalid context 0x0. This is a serious error. This
application, or a library it uses, is using an invalid context and is
thereby contributing to an overall degradation of system stability and
reliability. This notice is a courtesy: please fix this problem. It
will become a fatal error in an upcoming update.
大概是在抱怨 fillPixelBufferFromImage
中的 CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)
行。但是,删除 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)
}
是的,这是一个您应该担心的错误。说 "This is a serious error." 和 "please fix this problem" 的错误消息不是在开玩笑。
这是不正确的:
CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)
因为 none 个是这样的:
- 您不在 UIView 的
-drawRect:
方法中
- 您没有调用
UIGraphicsBeginImageContext
来设置上下文
- 您没有手动调用
UIGraphicsPushContext
因此,就 UIKit 所知,没有 "current" 上下文,所以 UIGraphicsGetCurrentContext()
returns nil.
您自己创建了位图上下文,因此您应该将比例应用于该上下文:
CGContextScaleCTM(context, scale, scale)
目标是将一系列视网膜图像转换为单个视频。
下面的两个函数负责将一个UIImage写入一个AVAssetWriterInputPixelBufferAdaptor。它们起作用了,并且代码从图像中生成了看似有效的视频。
然而,Xcode 抱怨这个错误:
CGContextScaleCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
大概是在抱怨 fillPixelBufferFromImage
中的 CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)
行。但是,删除 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)
}
是的,这是一个您应该担心的错误。说 "This is a serious error." 和 "please fix this problem" 的错误消息不是在开玩笑。
这是不正确的:
CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale)
因为 none 个是这样的:
- 您不在 UIView 的
-drawRect:
方法中 - 您没有调用
UIGraphicsBeginImageContext
来设置上下文 - 您没有手动调用
UIGraphicsPushContext
因此,就 UIKit 所知,没有 "current" 上下文,所以 UIGraphicsGetCurrentContext()
returns nil.
您自己创建了位图上下文,因此您应该将比例应用于该上下文:
CGContextScaleCTM(context, scale, scale)