6

I'm trying to get as good an image as possible from the camera, but can only find examples that captureStillImageAsynchronouslyFromConnection and then go straight to:

NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];    
UIImage *image = [[UIImage alloc] initWithData:imageData];

JPEG being lossy and all, is there any way to get the data as PNG, or even just RGBA (BGRA, what-have-you?). AVCaptureStillImageOutput doesn't seem to have any other NSData* methods....

Actually looking at the CMSampleBufferRef, it seems like it's already locked as JPEG ~

formatDescription = <CMVideoFormatDescription 0xfe5e1f0 [0x3e5ac650]> {
mediaType:'vide' 
mediaSubType:'jpeg' 
mediaSpecific: {
    codecType: 'jpeg'       dimensions: 2592 x 1936 
} 
extensions: {(null)}
}

Is there some other way to take a full-res picture and get the raw data?

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
Kaolin Fire
  • 2,521
  • 28
  • 43
  • So how did you end up getting the data for PNG? Did you just use kCVPixelFormatType_32BGRA instead of kCMVideoCodecType_JPEG? – Crashalot Mar 30 '16 at 07:43
  • Yes ~ https://github.com/blindsightcorp/rawphoto-ios/blob/master/RawPhoto/CaptureSessionManager.m – Kaolin Fire Mar 30 '16 at 19:41
  • thanks, but line 167 shows you using jpegStillImageNSDataRepresentation still? how do you convert to PNG? – Crashalot Mar 30 '16 at 19:45
  • My bad on the messy code — that's in a false ifdef. Line 104 is the key. (and 170-183). – Kaolin Fire Mar 30 '16 at 19:45
  • no problem, but where do you convert to PNG output? not clear ... – Crashalot Mar 30 '16 at 19:46
  • The above makes it a non-lossy UIImage. It's actually saved in line 135 of https://github.com/blindsightcorp/rawphoto-ios/blob/master/RawPhoto/MainViewController.m -- if you were up to updating the accepted answer to add this detail, that would be awesome :) – Kaolin Fire Mar 30 '16 at 19:50
  • ok will synthesize your comments for other readers, though will post as a separate answer first since to avoid modifying someone else's code without consent. if slugchewer wants, he will be free of course to incorporate the new answer. – Crashalot Mar 30 '16 at 19:55
  • Why did you set the scale to 1.0? Shouldn't the code use something like UIScreen.mainScreen().scale instead? – Crashalot Mar 30 '16 at 21:06
  • this line `let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)` is returning nil and breaking the rest of the code even though the buffer provided in the callback is not nil. did this ever happen to you? – Crashalot Mar 30 '16 at 23:33

2 Answers2

10

You'll need to set the outputSettings with a different pixel format. If you want 32-bit BGRA, for example, you can set:

NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil];

From https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVCaptureStillImageOutput_Class/Reference/Reference.html, the "recommended" pixel formats are:

  • kCMVideoCodecType_JPEG
  • kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
  • kCVPixelFormatType_32BGRA

Of course, if you're not using JPEG output, you can't use jpegStillImageNSDataRepresentation:, but there's an example here: how to convert a CVImageBufferRef to UIImage

Community
  • 1
  • 1
squidpickles
  • 1,737
  • 19
  • 27
  • Wow. I so should have just tried that, despite `availableImageDataCodecTypes` saying only jpeg was available. I suppose the others aren't codecs, so that makes sense. Much happier. Thanks! :) – Kaolin Fire Jul 26 '12 at 01:13
  • So if you want PNG instead of JPEG output, you use kCVPixelFormatType_32BGRA and then use one of the answers to convert from a CVImageBufferRef to UIImage? Thanks! – Crashalot Mar 30 '16 at 08:18
0

Just change the Output settings of your connection:

outputSettings The compression settings for the output.

@property(nonatomic, copy) NSDictionary *outputSettings

You can retreive an NSDictionary of the supported values with

availableImageDataCodecTypes The supported image codec formats that can be specified in outputSettings. (read-only)

@property(nonatomic, readonly) NSArray *availableImageDataCodecTypes
user1536580
  • 132
  • 4
  • A newly-created AVCaptureStillImageOutput gives an array with one item for availableImageDataCodecTypes: (jpeg). Does that mean I'm just completely SOL for "full res"? – Kaolin Fire Jul 20 '12 at 06:22