-->

拍摄静止的UIImage没有(从CMSampleBufferRef)压缩?(Capture stil

2019-08-17 21:25发布

我需要获得UIImage从CMSampleBufferRef 压缩前的图像数据。 我使用的代码:

captureStillImageOutput captureStillImageAsynchronouslyFromConnection:connection
 completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) 
{
    // that famous function from Apple docs found on a lot of websites
    // does NOT work for still images
    UIImage *capturedImage = [self imageFromSampleBuffer:imageSampleBuffer]; 
}

http://developer.apple.com/library/ios/#qa/qa1702/_index.html是一个链接imageFromSampleBuffer功能。

但它不能正常工作。 :(

有一个jpegStillImageNSDataRepresentation:imageSampleBuffer方法,但它给人的压缩数据(很好,因为JPEG)。

我怎样才能获得UIImage用最原始的非压缩数据捕获静止图像后产生的?

也许,我应该指定视频输出一些设置? 我目前使用的:

captureStillImageOutput = [[AVCaptureStillImageOutput alloc] init];
captureStillImageOutput.outputSettings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };

我注意到,该输出有一个默认值AVVideoCodecKey ,这是AVVideoCodecJPEG 。 能不能避免以任何方式或拍摄静止图像时做它甚至事

我发现了一些有: 从相机的RAW图像数据,如“645 PRO” ,但我只需要一个UIImage,而无需使用OpenCV的或OGLES或其他第三方。

Answer 1:

该方法imageFromSampleBuffer事实上确实工作,我使用的是更改后的版本的,但如果我没有记错的话,你需要设置outputSettings权利。 我认为你需要设置键kCVPixelBufferPixelFormatTypeKey和值kCVPixelFormatType_32BGRA

因此,例如:

NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;                                 
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];                
NSDictionary* outputSettings = [NSDictionary dictionaryWithObject:value forKey:key];

[newStillImageOutput setOutputSettings:outputSettings];

编辑

我使用这些设置采取stillImages没有视频。 是您sessionPreset AVCaptureSessionPresetPhoto? 有可能是与问题

AVCaptureSession *newCaptureSession = [[AVCaptureSession alloc] init];
[newCaptureSession setSessionPreset:AVCaptureSessionPresetPhoto];

编辑2

它保存到UIImage的部分是从文档的一个相同。 这是我问的问题的其他来源的原因,但我想这只是抓住了救命稻草。 还有另一种方法,我知道的,但是这需要OpenCV的。

- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

CVPixelBufferLockBaseAddress(imageBuffer, 0);

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);

}

我想这是没有帮助到你,对不起。 我不知道意犹未尽地想起其他来源为您的问题。



Answer 2:

这里有一个更有效的方法:

UIImage *image = [UIImage imageWithData:[self imageToBuffer:sampleBuffer]];

- (NSData *) imageToBuffer:(CMSampleBufferRef)source {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(source);
    CVPixelBufferLockBaseAddress(imageBuffer,0);

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    void *src_buff = CVPixelBufferGetBaseAddress(imageBuffer);

    NSData *data = [NSData dataWithBytes:src_buff length:bytesPerRow * height];

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    return data;
}


文章来源: Capture still UIImage without compression (from CMSampleBufferRef)?