保存原始图像数据与在iOS修改的元数据(重新编码无)(Save original image dat

2019-07-19 01:56发布

我想保存的图像在一个临时文件夹中的一些元数据的变化,无需重新编码的实际图像数据。

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

我已经尝试使用CGImageDestinationRef ( CGImageDestinationAddImageFromSource ),但它只能使用解码图像,这意味着的编码方式重新它,它在保存时被创建(测试像素字节会有所不同)。

是否有任何其他的方法/类适用于iOS,可以保存图像数据与元数据,除了使用CGImageDestinationRef ? 对于解决办法的建议也将受到欢迎。

Answer 1:

这是一个令人沮丧的问题与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这种差距的开源库。



Answer 2:

除了iPhone,EXIF,亚伦的答案,你可能也想看看的libexif C库 。

又见HCO23的回答
如何编写或修改EXIF数据在文件系统中现有的图像,而无需加载图像?

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

另外值得一提的是,许多“专业”的元数据编辑在App Store上的应用程序似乎通过创建边车/ XMP文件解决此问题裙子。



Answer 3:

试试这个 :

- (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;
}


文章来源: Save original image data with modified metadata (no re-encoding) on iOS