Преобразование CVImageBufferRef в PNG - PullRequest
4 голосов
/ 25 октября 2010

Я хочу записать все кадры на диск, используя QTKit.framework для ввода с камеры.Но все изображения, которые я получаю, наполовину прозрачны и без каких-либо цветов, может быть проблема с цветовым пространством?; (Они выглядят хорошими в предварительном просмотре, но когда я пишу им, «что-то» происходит. Интересно, что это такое.

-(void)savePNGImage:(CGImageRef)imageRef path:(NSString *)path {
    NSURL *outURL = [[NSURL alloc] initFileURLWithPath:path]; 
    CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((CFURLRef)outURL, (CFStringRef)@"public.png" , 1, NULL);
    CGImageDestinationAddImage(dr, imageRef, NULL);
    CGImageDestinationFinalize(dr);
    [outURL release];
}
-(void)saveJPEGImage:(CGImageRef)imageRef path:(NSString *)path {
    CFMutableDictionaryRef mSaveMetaAndOpts = CFDictionaryCreateMutable(nil, 0,
                                                                    &kCFTypeDictionaryKeyCallBacks,  &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(mSaveMetaAndOpts, kCGImageDestinationLossyCompressionQuality, 
                         [NSNumber numberWithFloat:1.0]);   // set the compression quality here
    NSURL *outURL = [[NSURL alloc] initFileURLWithPath:path];
    CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((CFURLRef)outURL, (CFStringRef)@"public.jpeg" , 1, NULL);
    CGImageDestinationAddImage(dr, imageRef, mSaveMetaAndOpts);
    CGImageDestinationFinalize(dr);
    [outURL release];
}


- (void)captureOutput:(QTCaptureOutput *)captureOutput 
  didOutputVideoFrame:(CVImageBufferRef)videoFrame 
     withSampleBuffer:(QTSampleBuffer *)sampleBuffer 
       fromConnection:(QTCaptureConnection *)connection{

    CVPixelBufferLockBaseAddress(videoFrame,0); 
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(videoFrame); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame); 
    size_t width = CVPixelBufferGetWidth(videoFrame); 
    size_t height = CVPixelBufferGetHeight(videoFrame); 
    CVPixelBufferUnlockBaseAddress(videoFrame,0);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, 
                                                        width, height, 8, 
                                                        bytesPerRow, 
                                                        colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
        CGImageRef frame = CGBitmapContextCreateImage(newContext); 

    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace);

    [self savePNGImage:frame path:[NSString stringWithFormat:@"/Users/nacho4d/Desktop/framesCam/frame%003d.png", frameNum++]];
[self saveJPEGImage:frame path:[NSString stringWithFormat:@"/Users/nacho4d/Desktop/framesCam/frame%003d.jpeg", frameNum++]];

    CGImageRelease(frame);
}

Атрибуты Capturer - это просто размер кадра и формат пикселя, например: [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], (id)kCVPixelBufferPixelFormatTypeKey

Обновление:

Я пробовал также с JPEG, и я получаю такое же изображение, как будто некоторые каналы не хватает изображения, и все записанные кадры имеют белый фон. (Так как JPEG делаетне разрешить прозрачность ??)

Оригинальный и письменный (JPEG) один:

alt text alt text (Я не показываю PNG, поскольку он прозрачный и его трудно увидетьв браузере)

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 18 октября 2011

Я не уверен, в чем ваша проблема, но вот как я сохраняю изображения на диск.Просто передайте CVImageBufferRef, полученный из метода делегата, и, конечно, ваш собственный URL, и он должен работать нормально.По крайней мере, это для меня.Удачи!

-(void)saveImage:(CVImageBufferRef)image toURL:(NSURL*)url{

    NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:image]];

    NSImage *_image = [[NSImage alloc] initWithSize:[imageRep size]];
    [_image addRepresentation:imageRep];

    NSData *bitmapData = [_image TIFFRep    resentation];
    NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:bitmapData];
    NSData *imageData = [bitmapRep representationUsingType:NSJPEGFileType properties:nil];

    [_image release];
    _image = [[NSImage alloc] initWithData:imageData];

    NSBitmapImageRep *imgRep = [[_image representations] objectAtIndex: 0];
    NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
    [data writeToFile: [self getSaveString] atomically: NO];

    [_image release];
}
1 голос
/ 25 января 2014

Я делаю что-то похожее и вижу ту же проблему.Я немного изменил ваш код и изменил kCGImageAlphaPremultipliedFirst на kCGImageAlphaNoneSkipFirst.Предположительно, потому что кадр не содержит альфа, хотя это 32 бит на пиксель, это решило проблему для меня.

1 голос
/ 07 ноября 2011

Вы разблокируете буфер изображения до того, как фактически его обработали.Попробуйте переместить эту строку:

CVPixelBufferUnlockBaseAddress(videoFrame,0);

в конец

...