下面的函数接受一个
UIImage
并从中返回一个CVPixelBuffer
,但它会移除alpha通道。class func pixelBufferFromImage(image: UIImage, pixelBufferPool: CVPixelBufferPool, size: CGSize) -> CVPixelBuffer {
var pixelBufferOut: CVPixelBuffer?
let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferPool, &pixelBufferOut)
if status != kCVReturnSuccess {
fatalError("CVPixelBufferPoolCreatePixelBuffer() failed")
}
let pixelBuffer = pixelBufferOut!
CVPixelBufferLockBaseAddress(pixelBuffer, [])
let data = CVPixelBufferGetBaseAddress(pixelBuffer)
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: data, width: Int(size.width), height: Int(size.height),
bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue)
context!.clear(CGRect(x: 0, y: 0, width: size.width, height: size.height))
let horizontalRatio = size.width / image.size.width
let verticalRatio = size.height / image.size.height
//aspectRatio = max(horizontalRatio, verticalRatio) // ScaleAspectFill
let aspectRatio = min(horizontalRatio, verticalRatio) // ScaleAspectFit
let newSize = CGSize(width: image.size.width * aspectRatio, height: image.size.height * aspectRatio)
let x = newSize.width < size.width ? (size.width - newSize.width) / 2 : 0
let y = newSize.height < size.height ? (size.height - newSize.height) / 2 : 0
context!.draw(image.cgImage!, in: CGRect(x: x, y: y, width: newSize.width, height: newSize.height))
CVPixelBufferUnlockBaseAddress(pixelBuffer, [])
return pixelBuffer
}
- 我知道初始图像中有一些像素具有特定的
alpha = 0
,因为如果我执行po image.pixelColor(atLocation: CGPoint(x: 0, y: 0))
,它会输出:
可选 - 一些: UIExtendedSRGBColorSpace 0 0 0 0
但生成的图像具有黑色背景。
我还尝试使用CGImageAlphaInfo.premultipliedLast.rawValue
,但这将导致图像变为蓝色,因此我假设RGBA
转换为ARGB
。但是,具有讽刺意味的是,这意味着ARGB
中的B为255,这将表明在RGBA
中A应该为0。
当使用CGContext
时,如何正确地将UIImage
alpha 转换为CVPixelBuffer
?
编辑1:
这是我的pixelBufferPool
代码。
func createPixelBufferAdaptor() {
let pixelFormatRGBA = kCVPixelFormatType_32RGBA //Fails
let pixelFormatARGB = kCVPixelFormatType_32ARGB //Works
let sourcePixelBufferAttributesDictionary = [
kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: pixelFormatARGB),
kCVPixelBufferWidthKey as String: NSNumber(value: Float(renderSettings.width)),
kCVPixelBufferHeightKey as String: NSNumber(value: Float(renderSettings.height))
]
pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoWriterInput,
sourcePixelBufferAttributes: sourcePixelBufferAttributesDictionary)
}
只有当我使用kCVPixelFormatType_32ARGB
时它才能正常工作。所谓的“正常工作”是指当我尝试使用缓冲池时。
let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferPool, &pixelBufferOut)
if status != kCVReturnSuccess {
fatalError("CVPixelBufferPoolCreatePixelBuffer() failed")
}
如果我使用RGBA
版本,则会失败,但如果我使用ARGB
版本,则可以成功。
pixelBufferPool
的代码。您是否在属性中传递了键kCVPixelBufferPixelFormatTypeKey
,并将其设置为kCVPixelFormatType_32RGBA
? - Eugene DudnykkCVPixelFormatType_32ARGB
,这就解释了为什么我的A
值是255,但是不合理的是,图片中确实有蓝色,所以B
值应该是0。尽管如此,我试图切换到RGBA
来测试我的理论,但会导致崩溃。上面的Edit 1
描述了发生了什么。谢谢! - impression7vx