调整captureStillImageBracketAsynchronouslyFromConnection提供的CMSampleBufferRef:withSettingsArray:completionHandler:

在我正在开发的应用程序中,我们正在拍摄需要4:3宽高比的照片,以便最大化我们捕获的视野。 直到现在我们还在使用AVCaptureSessionPreset640x480预设,但现在我们需要更大的分辨率。

据我所知,其他两种4:3格式是2592×1936和3264×2448。 由于这些对于我们的用例来说太大了,我需要一种缩小它们的方法。 我查看了一堆选项,但没有找到一种方法(优选没有复制数据)以有效的方式执行此操作而不会丢失exif数据。

vImage是我调查过的事情之一,但据我所知,数据需要被删除,exif数据将会丢失。 另一个选择是从jpegStillImageNSDataRepresentation提供的数据创建UIImage ,缩放它并获取数据。 这种方法似乎也剥夺了exif数据。

这里理想的方法是直接调整缓冲区内容的大小并调整照片的大小。 有谁知道我会怎么做呢?

我最终使用ImageIO来resize。 将这段代码放在这里以防万一有人遇到同样的问题,因为我花了太多时间在这上面。

此代码将保留exif数据,但会创建图像数据的副本。 我运行了一些基准测试 – 这个方法的执行时间在iPhone6上为0.05秒,使用AVCaptureSessionPresetPhoto作为原始照片的预设。

如果有人确实有更优化的解决方案,请发表评论。

 - (NSData *)resizeJpgData:(NSData *)jpgData { CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)jpgData, NULL); // Create a copy of the metadata that we'll attach to the resized image NSDictionary *metadata = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)); NSMutableDictionary *metadataAsMutable = [metadata mutableCopy]; // Type of the image (eg public.jpeg) CFStringRef UTI = CGImageSourceGetType(source); NSDictionary *options = @{ (id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue, (id)kCGImageSourceThumbnailMaxPixelSize: @(MAX(FORMAT_WIDTH, FORMAT_HEIGHT)), (id)kCGImageSourceTypeIdentifierHint: (__bridge NSString *)UTI }; CGImageRef resizedImage = CGImageSourceCreateThumbnailAtIndex(source, 0, (CFDictionaryRef)options); NSMutableData *destData = [NSMutableData data]; CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)destData, UTI, 1, NULL); if (!destination) { NSLog(@"Could not create image destination"); } CGImageDestinationAddImage(destination, resizedImage, (__bridge CFDictionaryRef) metadataAsMutable); // Tell the destination to write the image data and metadata into our data object BOOL success = CGImageDestinationFinalize(destination); if (!success) { NSLog(@"Could not create data from image destination"); } if (destination) { CFRelease(destination); } CGImageRelease(resizedImage); CFRelease(source); return destData; }