获取UIImage时如何消除Alpha通道的CVPixelBuffer

4
下面的函数接受一个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
    }
  1. 我知道初始图像中有一些像素具有特定的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版本,则可以成功。


2
请附上创建pixelBufferPool的代码。您是否在属性中传递了键kCVPixelBufferPixelFormatTypeKey,并将其设置为kCVPixelFormatType_32RGBA - Eugene Dudnyk
我原本使用的是 kCVPixelFormatType_32ARGB,这就解释了为什么我的 A 值是255,但是不合理的是,图片中确实有蓝色,所以 B 值应该是0。尽管如此,我试图切换到 RGBA 来测试我的理论,但会导致崩溃。上面的 Edit 1 描述了发生了什么。谢谢! - impression7vx
1个回答

3
很遗憾,我对这个话题的范围过于狭窄(讽刺的是,大多数问题都被认为范围过广)。 我试图创建一个视频,其中包括使用AVCaptureSession和AVAssetWriter,并且其中一些图片具有深度图,然后我会将其生成以将某些像素转换为清晰颜色。但是,通过一些研究,我发现对于图像和显示它们来说,alpha通道是维护的。但是,在视频中,这是不可能的。(如何使用AVFoundation播放具有Alpha通道的视频?) (iOS中带透明背景的视频) (A-frame: 透明视频的问题) (是否可以播放带有Alpha通道的视频?) 无论如何,我的下一个目标是执行一些答案所描述的ChromaKey,要么是从深度图应用于我的特征的掩蔽。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接