在iOS上使用修改后的元数据(无重新编码)保存原始图像数据

我想在临时文件夹中保存一些元数据更改的图像,而不重新编码实际的图像数据。

我发现能够做到这一点的唯一方法是ALAssetsLibrary / writeImageDataToSavedPhotosAlbum:metadata:completionBlock:但是,这个将图像保存到照片库。 相反,我想将图像保存到临时文件夹(例如,通过电子邮件共享它,而不填充照片库)。

我尝试过使用CGImageDestinationRef ( CGImageDestinationAddImageFromSource ),但它只能使用解码图像创建,这意味着它在保存时会重新编码(测试时,像素字节看起来不同)。

除了使用CGImageDestinationRef之外,还有其他可用于iOS的方法/类可以保存图像数据和元数据吗? 对于变通方法的建议也会受到欢迎。

这是iOS SDK令人沮丧的问题。 首先,我建议提交增强请求 。

现在,这是一个潜在的解决方法:如果您创建了ALAsset(即,其editable属性为YES ),那么您基本上可以读取数据,使用元数据进行写入,再次读取,保存到磁盘,然后使用原始元数据进行写入。

此方法将避免创建重复的图像。

请阅读//注释,因为我为了简洁起见省略了一些内容(比如构建元数据字典):

 ALAsset* asset; //get your asset, don't use this empty one if (asset.editable) { // get the source data ALAssetRepresentation *rep = [asset defaultRepresentation]; Byte *buffer = (Byte*)malloc(rep.size); // add error checking here NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil]; NSData *sourceData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; // make your metadata whatever you want // you should use actual metadata, not a blank dictionary NSDictionary *metadataDictionary = [NSDictionary dictionary]; // these are __weak to avoid creating an ARC retain cycle NSData __weak *originalData = sourceData; NSDictionary __weak *originalMetadata = [rep metadata]; [asset setImageData:sourceData metadata:metadataDictionary completionBlock:^(NSURL *assetURL, NSError *error) { //now get your data and write it to file if (!error) { //get your data... NSString *assetPath = [assetURL path]; NSData *targetData = [[NSFileManager defaultManager] contentsAtPath:assetPath]; //...write to file... NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentPath = [searchPaths lastObject]; NSURL *fileURL = [NSURL fileURLWithPath:documentPath]; [targetData writeToURL:fileURL atomically:YES]; //...and put it back the way it was [asset setImageData:originalData metadata:originalMetadata completionBlock:nil]; } else { // handle error on setting data NSLog(@"ERROR: %@", [error localizedDescription]); } }]; } else { // you'll need to make a new ALAsset which you have permission to edit and then try again } 

如您所见,如果您不拥有ALAsset,则需要创建一个,这会将照片添加到用户的库中,这正是您想要避免的。 但是,正如您可能已经猜到的那样,即使您的应用程序创建了ALAsset,也无法从用户的照片库中删除ALAsset。 (随意提交另一个增强请求。)

因此,如果照片/图片是在您的应用中创建的,那么这对您有用。

但如果没有,它将创建用户必须删除的附加副本。

唯一的选择是自己解析NSData,这将是一个痛苦。 我知道没有开源库可以填补iOS SDK中的这个空白。

除了iphone-exif和Aaron的答案之外,您可能还想查看libexif c库 。

另见HCO23的回答
如何在不加载图像的情况下为文件系统上的现有图像编写或修改EXIF数据?

(@ HCO23在iOS项目中使用了libexif)。

值得注意的是,应用程序商店中的许多“专业”元数据编辑应用程序似乎都是通过创建sidecar / xmp文件来解决这个问题。

尝试这个 :

 - (void)saveImage: (UIImage*)image { if (image != nil) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString* path = [documentsDirectory stringByAppendingPathComponent: @"test.png" ]; NSData* data = UIImagePNGRepresentation(image); [data writeToFile:path atomically:YES]; } } - (UIImage*)loadImage { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString* path = [documentsDirectory stringByAppendingPathComponent: @"test.png" ]; UIImage* image = [UIImage imageWithContentsOfFile:path]; [self sendAction:path]; return image; }