我需要转换UIImage
为NSData
但不使用UIImagePngRepresentation
or UIImageJpegRepresentation
,对于来自 photolib 的图像,我可以使用此处提到的 assetslib 方法Using ALAssetsLibrary 和 ALAsset 取出 Image as NSData,但对于捕获的图像,资产 url 不存在因此在这种情况下我需要转换UIImage
直接到带有exif数据的字节,我怎么能做到这一点?请帮忙
3 回答
我遇到了类似的问题,但出于安全原因,我不想按照 Wes 的建议将数据写入默认文件系统。我还希望能够将元数据添加到我的图像中。我的解决方案如下:
- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype
{
NSMutableData *imageData = [NSMutableData data];
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL);
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL);
if (imageDestination == NULL)
{
NSLog(@"Failed to create image destination");
imageData = nil;
}
else
{
CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata);
if (CGImageDestinationFinalize(imageDestination) == NO)
{
NSLog(@"Failed to finalise");
imageData = nil;
}
CFRelease(imageDestination);
}
CFRelease(uti);
return imageData;
}
要使用它,您将执行以下操作:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg!
// you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to.
// convert to NSData
NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType];
// ...
}
H巴斯坦,
根据您的评论:
...我想通过文档目录中的 UIImagepicker 委托方法保存设备相机返回的捕获图像...
看起来您的真正目标是将带有 EXIF 数据的图像保存到文档目录,而不是专门将 UIImage 作为带有 EXIF 数据的 NSData 对象。在这种情况下,您可以在实施中执行以下操作imagePickerController:didFinishPickingMediaWithInfo:
// Get your image.
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
// Get your metadata (includes the EXIF data).
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
// Create your file URL.
NSFileManager *defaultManager = [NSFileManager defaultManager];
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"];
// Set your compression quuality (0.0 to 1.0).
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL);
if (imageDestination == NULL ) {
// Handle failure.
NSLog(@"Error -> failed to create image destination.");
return;
}
// Add your image to the destination.
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata);
// Finalize the destination.
if (CGImageDestinationFinalize(imageDestination) == NO) {
// Handle failure.
NSLog(@"Error -> failed to finalize the image.");
}
CFRelease(imageDestination);
根据我的测试,执行时间与执行时间大致相同或更快:
NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0);
[data writeToURL:outputURL atomically:YES];
...您可以保留 EXIF 数据!
如果你想确保你的 UI 保持响应,你也可以将它分派到后台队列:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Do the image saving here...
});
重要提示:您需要将ImageIO.framework
和添加MobileCoreServices.framework
到目标的构建阶段,并将它们导入到您执行图像保存的类中:
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
其他说明 我的理解是,在这种情况下,我们不会在按照示例中的建议保存图像时产生生成损失。我们正在使用 UIImage 的 CGImage 属性,正如文档所述:
底层 Quartz 图像数据
你可以尝试这样的事情。不确定它是否是最好的方法。但值得一试。如果图片 URL 可用,您可以尝试initWithContentsOfUrl
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];