在Objective-C中剥离所有Exif数据 [英] Stripping All Exif Data in Objective-C

查看:73
本文介绍了在Objective-C中剥离所有Exif数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用Objective-C剥离UIImage中的所有exif数据?我已经可以使用以下命令获取exif数据:

How do you strip all exif data in a UIImage using objective-c? I have been able to get the exif data using the following :

NSData* pngData =  UIImagePNGRepresentation(image);
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

NSDictionary* dic   =   nil;
if ( NULL == imageSource )
{
    #ifdef _DEBUG
    CGImageSourceStatus status = CGImageSourceGetStatus ( source );
    NSLog ( @"Error: file name : %@ - Status: %d", file, status );
    #endif
}
else
{
    CFDictionaryRef propertyRef = CGImageSourceCopyPropertiesAtIndex ( imageSource, 0, NULL );
    CGImageMetadataRef metadataRef = CGImageSourceCopyMetadataAtIndex ( imageSource, 0, NULL );
    // CFDictionaryRef metadataRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyExifDictionary);
    if (metadataRef) {
        NSDictionary* immutableMetadata = (NSDictionary *)metadataRef;
        if ( immutableMetadata ) {
            dic = [ NSDictionary dictionaryWithDictionary : (NSDictionary *)metadataRef ];
        }   
        CFRelease ( metadataRef );
    }
    CFRelease(imageSource);
    imageSource = nil;
}


return dic;

推荐答案

一些想法:

  1. 通常,将图像从NSData或文件内容加载到UIImage,用UIImagePNGRepresentation重新提取数据并将其保存回NSData的过程如下:从图像中删除元数据.

  1. Generally the process of loading an image from the NSData or from the contents of a file into a UIImage, re-extracting the data with UIImagePNGRepresentation and saving that back to a NSData will strip the metadata from the image.

但是,这种简单的技术有其缺点.值得注意的是,将其强制为PNG表示的过程可能会极大地影响输出NSData的大小.例如,如果原始图像是压缩的JPEG(例如由相机捕获),则生成的PNG文件实际上可能大于原始JPEG.

This simple technique has its disadvantages, though. Notably, the process of forcing it to a PNG representation may affect the size of the output NSData dramatically, though. For example, if the original image was a compressed JPEG (such as captured by the camera), the resulting PNG file can actually be larger than the original JPEG.

通常,我希望获取原始数据(如果将文档或文档包中的文件直接加载到NSData中;如果是从ALAssetsLibrary中检索到的内容,则我将检索ALAsset,然后然后从ALAssetRepresentation开始,然后从getBytes获取该原始资产的原始二进制表示形式).这样可以避免通过UIImage(特别是如果随后使用UIImagePNGRepresentationUIImageJEPGRepresentation)来回传递它.

Generally I would prefer to get the original data (if a file in Documents or the bundle, load that directly to a NSData; if it's something retrieved from the ALAssetsLibrary, I would retrieve the ALAsset, and from that, the ALAssetRepresentation, and from that I'd use getBytes to get the original binary representation of that original asset). This avoids the round-tripping it through a UIImage (particularly if subsequently using UIImagePNGRepresentation or UIImageJEPGRepresentation).

如果要剥离exif数据,可以:

If you want to strip exif data, you can:

  • 从原始NSData;

使用相同的图片数量"(几乎始终为1)和类型"创建图片目标;

Create an image destination, using the same "number of images" (almost always 1) and the "type";

将图像从源复制到目标时,告诉它适当的键(kCGImagePropertyExifDictionarykCGImagePropertyGPSDictionary应该设置为kCFNull),根据CGImageDestinationAddImageFromSource文档,该方法是您可以指定如果它们恰巧出现在源代码中,则应将它们从目标位置删除.

When copying the images from the source to the destination, tell it that the appropriate keys (kCGImagePropertyExifDictionary and kCGImagePropertyGPSDictionary should be set to kCFNull), which according to the CGImageDestinationAddImageFromSource documentation is how you specify that those should be removed in the destination if they happened to appear in the source).

因此,它可能看起来像:

Thus, it might look like:

- (NSData *)dataByRemovingExif:(NSData *)data
{
    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data, NULL);
    NSMutableData *mutableData = nil;

    if (source) {
        CFStringRef type = CGImageSourceGetType(source);
        size_t count = CGImageSourceGetCount(source);
        mutableData = [NSMutableData data];

        CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)mutableData, type, count, NULL);

        NSDictionary *removeExifProperties = @{(id)kCGImagePropertyExifDictionary: (id)kCFNull,
                                               (id)kCGImagePropertyGPSDictionary : (id)kCFNull};

        if (destination) {
            for (size_t index = 0; index < count; index++) {
                CGImageDestinationAddImageFromSource(destination, source, index, (__bridge CFDictionaryRef)removeExifProperties);
            }

            if (!CGImageDestinationFinalize(destination)) {
                NSLog(@"CGImageDestinationFinalize failed");
            }

            CFRelease(destination);
        }

        CFRelease(source);
    }

    return mutableData;
}

请注意,GPS信息从技术上讲不是exif数据,但我想您也想删除它.如果要保留GPS数据,请从我的removeExifProperties词典中删除kCGImagePropertyGPSDictionary条目.

Note, GPS information is not technically exif data, but I assume you wanted to remove that, too. If you wanted to keep the GPS data, remove the kCGImagePropertyGPSDictionary entry from my removeExifProperties dictionary.

BTW,在提取元数据的代码中,您似乎将CGImageMetadataRef强制转换为NSDictionary.如果您的技术可行,那很好,但是我认为CGImageMetadataRef被认为是一种不透明的数据类型,确实应该使用CGImageMetadataCopyTags来提取标签数组:

BTW, in your code to extract the meta data, you seem to be casting the CGImageMetadataRef as a NSDictionary. If your technique works, that's fine, but I think that CGImageMetadataRef is considered to be an opaque data type, and that one really should be using CGImageMetadataCopyTags to extract the array of tags:

- (NSArray *)metadataForData:(NSData *)data
{
    NSArray *metadataArray = nil;
    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data, NULL);

    if (source) {
        CGImageMetadataRef metadata = CGImageSourceCopyMetadataAtIndex(source, 0, NULL);
        if (metadata) {
            metadataArray = CFBridgingRelease(CGImageMetadataCopyTags(metadata));
            CFRelease(metadata);
        }
        CFRelease(source);
    }

    return metadataArray;
}

为了完整起见,在7.0之前的iOS版本中,您可以从属性中提取数据:

For the sake of completeness, in iOS versions prior to 7.0, you can extract the data from the properties:

- (NSDictionary *)metadataForData:(NSData *)data
{
    NSDictionary *properties = nil;
    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data, NULL);

    if (source) {
        properties = CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL));
        CFRelease(source);
    }

    return properties;
}

这篇关于在Objective-C中剥离所有Exif数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆