2013-01-17 66 views
3

我使用AVCaptureSession捕獲視頻。 但我想將捕獲的圖像轉換爲UIImage。將CMSampleBufferRef轉換爲UIImage

我發現在互聯網上的一些代碼:

- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer 
{ 

    NSLog(@"imageFromSampleBuffer: called"); 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
               bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 


    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return (image); 
} 

但我得到了一些錯誤:

Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 2560 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst. 
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextCreateImage: invalid context 0x0 
2013-01-17 17:39:25.896 ThinkOutsideTheBox[2363:907] image <UIImage: 0x1d553f00> 
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGContextDrawImage: invalid context 0x0 
Jan 17 17:39:25 iPhone-4-de-XXX ThinkOutsideTheBox[2363] <Error>: CGBitmapContextGetData: invalid context 0x0 

編輯: 我也用的UIImage得到RGB色彩:

-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection 
{ 

    UIImage* image = [self imageFromSampleBuffer:sampleBuffer]; 
    unsigned char* pixels = [image rgbaPixels]; 
    double totalLuminance = 0.0; 
    for(int p=0;p<image.size.width*image.size.height*4;p+=4) 
    { 
     totalLuminance += pixels[p]*0.299 + pixels[p+1]*0.587 + pixels[p+2]*0.114; 
    } 
    totalLuminance /= (image.size.width*image.size.height); 
    totalLuminance /= 255.0; 
    NSLog(@"totalLuminance %f",totalLuminance); 

} 
+0

根據警告,當您收到上述錯誤時,「width」,「height」和「bytesPerRow」值的值是多少?這聽起來像你的圖像緩衝區正在被釋放,然後再嘗試使用它(可能是由於處理是在單獨的線程上完成的)。 –

+0

你也確定你在捕捉RGB樣本嗎?其他類型更緊湊,因此bytesPerRow小於適合RGB緩衝區寬度的字節。 – Tommy

+0

如果添加'NSLog(@「像素格式:0x%x」,CVPixelBufferGetPixelFormatType(imageBuffer));'那裏有什麼日誌輸出? –

回答

7

您最好的選擇是將set the capture video data output's videoSettings轉換爲specifies the pixel format you want的字典,您需要在CGBitmapContext可以處理的RGB上設置一些變體。

該文檔有a list of all of the pixel formats that Core Video can process。 CGBitmapContext僅支持其中一小部分。您在互聯網上找到的代碼的格式爲kCVPixelFormatType_32BGRA,但可能是針對iOS設備上的Mac編寫的,kCVPixelFormatType_32ARGB(big-endian)可能會更快。在設備上試試它們兩個,,並比較幀速率。

+1

iOS似乎不支持「kCVPixelFormatType_32ARGB」。 AVCaptureOutput.h列出了支持的格式。此平臺上的可用像素格式類型爲(420v,420f,BGRA)。 – demon

+0

@demon所以如果BGRA是可用的格式之一,那麼匹配鍵將是kCVPixelFormatType_32BGRA,並且這個鍵將用於捕獲PNG? – Crashalot

+0

@Crashalot首先,您的視頻必須包含Alpha通道,否則它毫無意義。 – demon