调整 captureStillImageBracketAsynchronouslyFromConnection:withSettingsArray:completionHandler 提供的 CMSampleBufferRef 的大小:
Resizing CMSampleBufferRef provided by captureStillImageBracketAsynchronouslyFromConnection:withSettingsArray:completionHandler:
在我正在开发的应用中,我们拍摄的照片需要具有 4:3 纵横比,以便最大化我们拍摄的视野。到目前为止,我们一直在使用 AVCaptureSessionPreset640x480
预设,但现在我们需要更大的分辨率。
据我所知,仅有的其他两种 4:3 格式是 2592x1936 和 3264x2448。由于这些对于我们的用例来说太大了,我需要一种方法来缩小它们的尺寸。我研究了很多选项,但没有找到一种方法(最好不复制数据)在不丢失 exif 数据的情况下以有效的方式执行此操作。
vImage
是我调查的事情之一,但据我所知,数据需要被复制并且 exif 数据会丢失。另一种选择是根据 jpegStillImageNSDataRepresentation
提供的数据创建 UIImage
,缩放它并取回数据。这种方法似乎也剥离了 exif 数据。
这里的理想方法是直接调整缓冲区内容的大小并调整照片的大小。有谁知道我会怎么做?
我最终使用 ImageIO 来调整大小。将这段代码留在这里以防有人遇到同样的问题,因为我在这上面花了太多时间。
此代码将保留 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 (e.g. 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;
}
在我正在开发的应用中,我们拍摄的照片需要具有 4:3 纵横比,以便最大化我们拍摄的视野。到目前为止,我们一直在使用 AVCaptureSessionPreset640x480
预设,但现在我们需要更大的分辨率。
据我所知,仅有的其他两种 4:3 格式是 2592x1936 和 3264x2448。由于这些对于我们的用例来说太大了,我需要一种方法来缩小它们的尺寸。我研究了很多选项,但没有找到一种方法(最好不复制数据)在不丢失 exif 数据的情况下以有效的方式执行此操作。
vImage
是我调查的事情之一,但据我所知,数据需要被复制并且 exif 数据会丢失。另一种选择是根据 jpegStillImageNSDataRepresentation
提供的数据创建 UIImage
,缩放它并取回数据。这种方法似乎也剥离了 exif 数据。
这里的理想方法是直接调整缓冲区内容的大小并调整照片的大小。有谁知道我会怎么做?
我最终使用 ImageIO 来调整大小。将这段代码留在这里以防有人遇到同样的问题,因为我在这上面花了太多时间。
此代码将保留 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 (e.g. 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;
}