目标 c - 在 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,即使您的应用创建了它。(请随时为此提交另一个增强请求。

因此,如果照片/图像是在您的应用程序中创建的,这将对您有用。

但如果没有,它将创建一个用户必须删除的其他副本。

唯一的选择是自己解析 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;
}

最新更新