2016-02-24 6 views
0

Извините, для этого вопроса, я знаю, есть аналогичный вопрос, но я не могу получить ответ на работу. Вероятно, какая-то глупая ошибка на моей стороне ;-)iOS: Наложение двух изображений с помощью альфа-экрана

Я хочу наложить два изображения с помощью Alpha на iOS. Изображения, взятые из двух видеороликов, считанные AssetReader и хранящиеся в двух CVPixelBuffer. Я знаю, что канал Alpha не сохраняется в видео, поэтому я получаю его из третьего файла. Все данные выглядят отлично. Проблема заключается в наложении, если я делаю это на экране с помощью [CIContext drawImage], все в порядке! Но если я делаю это за кадром, потому что формат видео не идентичен формату экрана, я не могу заставить его работать: 1. drawImage действительно работает, но только на экране 2. render: toCVPixelBuffer работает, но игнорирует Альфа 3. CGContextDrawImage, кажется, не делать ничего вообще (даже не сообщение об ошибке)

Так может кто-нибудь дать мне представление о том, что это не так:

Init: ... (много кода перед) Настройка цветового пространства и растрового контекста

    if(outputContext) 
        { 
         CGContextRelease(outputContext); 
         CGColorSpaceRelease(outputColorSpace); 
        } 
        outputColorSpace = CGColorSpaceCreateDeviceRGB(); 
        outputContext = CGBitmapContextCreate(CVPixelBufferGetBaseAddress(pixelBuffer), videoFormatSize.width, videoFormatSize.height, 8, CVPixelBufferGetBytesPerRow(pixelBuffer), outputColorSpace,(CGBitmapInfo) kCGBitmapByteOrderDefault |kCGImageAlphaPremultipliedFirst); 

... (много кода после)

Чертеж:

CIImage *backImageFromSample; 
CGImageRef frontImageFromSample; 
CVImageBufferRef nextImageBuffer = myPixelBufferArray[0]; 
CMSampleBufferRef sampleBuffer = NULL; 
CMSampleTimingInfo timingInfo; 

//draw the frame 
CGRect toRect; 
toRect.origin.x = 0; 
toRect.origin.y = 0; 
toRect.size = videoFormatSize; 

//background image always full size, this part seems to work 
if(drawBack) 
{ 
    CVPixelBufferLockBaseAddress(backImageBuffer, kCVPixelBufferLock_ReadOnly); 
    backImageFromSample = [CIImage imageWithCVPixelBuffer:backImageBuffer]; 
    [coreImageContext render:backImageFromSample toCVPixelBuffer:nextImageBuffer bounds:toRect colorSpace:rgbSpace]; 
    CVPixelBufferUnlockBaseAddress(backImageBuffer, kCVPixelBufferLock_ReadOnly); 
} 
else 
    [self clearBuffer:nextImageBuffer]; 
//Front image doesn't seem to do anything 
if(drawFront) 
{ 
    unsigned long int numBytes = CVPixelBufferGetBytesPerRow(frontImageBuffer)*CVPixelBufferGetHeight(frontImageBuffer); 
    CVPixelBufferLockBaseAddress(frontImageBuffer, kCVPixelBufferLock_ReadOnly); 

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, CVPixelBufferGetBaseAddress(frontImageBuffer), numBytes, NULL); 
    frontImageFromSample = CGImageCreate (CVPixelBufferGetWidth(frontImageBuffer) , CVPixelBufferGetHeight(frontImageBuffer), 8, 32, CVPixelBufferGetBytesPerRow(frontImageBuffer), outputColorSpace, (CGBitmapInfo) kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst, provider, NULL, NO, kCGRenderingIntentDefault); 
    CGContextDrawImage (outputContext, inrect, frontImageFromSample); 
    CVPixelBufferUnlockBaseAddress(frontImageBuffer, kCVPixelBufferLock_ReadOnly); 
    CGImageRelease(frontImageFromSample); 
} 

Любые идеи кто-нибудь?

+0

Если вы ищете, возможно, лучший способ сохранить альфа-видео в вашем приложении расслоении, то есть взглянуть на: http://stackoverflow.com/a/21079559/763355 – MoDJ

+0

Да, я видел примеры, которые разделяют видео с Alpha на два видео один цвет + один оттенок серого, но я решил против него. Идея моей реализации заключалась в том, чтобы использовать GPU для кодирования видео и CPU для кодирования маски. Это позволяет мне делать это в реальном времени даже с камеры ... – BetaVersion

ответ

1

Поэтому, очевидно, я должен прекратить задавать вопросы о стеке. Каждый раз, когда я делаю это после нескольких часов отладки, я сразу же нахожу ответ. Простите за это. Проблема заключается в инициализации, вы не можете делать CVPixelBufferGetBaseAddress без блокировки первых адресов O_o. Адрес получает NULL, и, похоже, это разрешено, и действие не делает ничего. Таким образом, правильный код:

   if(outputContext) 
       { 
        CGContextRelease(outputContext); 
        CGColorSpaceRelease(outputColorSpace); 
       } 
       CVPixelBufferLockBaseAddress(pixelBuffer); 
       outputColorSpace = CGColorSpaceCreateDeviceRGB(); 
       outputContext = CGBitmapContextCreate(CVPixelBufferGetBaseAddress(pixelBuffer), videoFormatSize.width, videoFormatSize.height, 8, CVPixelBufferGetBytesPerRow(pixelBuffer), outputColorSpace,(CGBitmapInfo) kCGBitmapByteOrderDefault |kCGImageAlphaPremultipliedFirst); 
       CVPixelBufferUnlockBaseAddress(pixelBuffer);