从iPhone摄像头(AVCaptureSession)捕获24 bpp位图中的图像

我使用AVCaptureSession从iPhone的前置摄像头捕获帧。 我试图改变AVCaptureVideoDataOutput的格式,以便它可以捕获一个24 bpp的位图。 这段代码为我提供了一个没有任何问题的32 bpp位图:

AVCaptureVideoDataOutput *outputDevice = [[AVCaptureVideoDataOutput alloc] init]; outputDevice.videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey: (id)kCVPixelBufferPixelFormatTypeKey]; [outputDevice setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 

但是,当我将其更改为24时,会在该行上崩溃。

 outputDevice.videoSettings = [NSDictionary dictionaryWithObject: [NSNumber numberWithInt:kCVPixelFormatType_24RGB] forKey: (id)kCVPixelBufferPixelFormatTypeKey]; 

我怎样才能在24 bpp中捕捉图像? 为什么它失败* kCVPixelFormatType_24RGB *? 解决方法是将32 bmp转换为24,但我还没有find如何做到这一点。

它崩溃,因为iPhone不支持kCVPixelFormatType_24RGB 。 现代iPhone中唯一支持的像素格式是:

  • kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
  • kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
  • kCVPixelFormatType_32BGRA

您可以将其中任何一个转换为RGB,但BGRA缓冲区转换更简单。 有很多方法可以做到这一点(在这里和谷歌search的例子),但这是一个非常简单的方法:

 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { @autoreleasepool { CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); CVPixelBufferLockBaseAddress(imageBuffer,0); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); uint8_t *sourceBuffer = (uint8_t*)CVPixelBufferGetBaseAddress(imageBuffer); CVPixelBufferUnlockBaseAddress(imageBuffer, 0); int bufferSize = bytesPerRow * height; uint8_t *bgraData = malloc(bufferSize); memcpy(bgraData, sourceBuffer, bufferSize); uint8_t *rgbData = malloc(width * height * 3); int rgbCount = 0; for (int i = 0; i < height; i++) { for (int ii = 0; ii < width; ii+=4) { int current = (i * height)+ii; rgbData[rgbCount] = bgraData[current + 2]; rgbData[rgbCount + 1] = bgraData[current + 1]; rgbData[rgbCount + 2] = bgraData[current]; rgbCount+=3; } } // // Process rgbData // free (rgbData); } } 

顺便说一句,这是8bpp(不是24bpp); 构成24位图像的三个八位平面或者构成32位图像的四个平面。 另外值得指出的是,在大多数情况下,使用32位数据并忽略alpha通道,而不是转换为24位可能更简单快捷。