UIImage, получающий CVPixelBuffer, удаляет альфу

Функция ниже принимает UIImage и возвращает CVPixelBuffer из UIImage, но удаляет альфа-канал.

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 меняются местами. Но, по иронии судьбы, это будет означать, что B в ARGB равно 255, что указывает на то, что в RGBA A будет 255, а должно быть 0.

Как я могу правильно перевести альфа-канал UIImage в CVPixelBuffer при использовании CGContext?

Редактировать 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.


person impression7vx    schedule 03.08.2019    source источник
comment
Пожалуйста, приложите код, как вы создаете pixelBufferPool. Вы передаете туда в атрибутах ключ kCVPixelBufferPixelFormatTypeKey как kCVPixelFormatType_32RGBA?   -  person Eugene Dudnyk    schedule 06.08.2019
comment
Я не был. Я использовал kCVPixelFormatType_32ARGB which makes sense why my A`, это будет 255, но это не имеет смысла, потому что у меня на картинке был синий цвет, а B должен быть 0. Тем не менее, я попытался переключиться на RGBA, чтобы проверить свою теорию, и это привело к сбою. Edit 1 выше описывает, что происходит. Спасибо!   -  person impression7vx    schedule 06.08.2019


Ответы (1)


Что ж, к сожалению, мои возможности для этой темы были слишком узкими (иронично, поскольку большинство вопросов считаются слишком широкими).

Я пытался создать видео из AVCaptureSession вместе с AVAssetWriter, и у некоторых изображений была карта глубины, которую я затем создавал, чтобы преобразовать некоторые пиксели в чистый цвет. Что ж, с некоторыми исследованиями я обнаружил, что для изображений и их отображения поддерживается альфа-канал. Но для видео это невозможно.

Как вы воспроизводите видео с альфа-каналом, используя AVFoundation? https://andreygordeev.com/2017/07/01/video-with-transparent-background-ios/ https://github.com/aframevr/aframe/issues/3205 https://www.reddit.com/r/swift/comments/3cw4le/is_it_possible_to_play_a_video_with_an_alpha/

Во всяком случае, моя следующая цель - сделать ChromaKey, как описано в некоторых ответах - либо это, либо маскирование из карты глубины, примененной к моим функциям.

person impression7vx    schedule 11.08.2019