首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >摘除目标C中的所有Exif数据

摘除目标C中的所有Exif数据
EN

Stack Overflow用户
提问于 2014-08-31 05:06:27
回答 2查看 6.4K关注 0票数 7

如何使用objective将UIImage中的所有exif数据剥离?我已经能够使用以下方法获得exif数据:

代码语言:javascript
运行
复制
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;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-31 19:27:30

有几个想法:

  1. 通常,将图像从NSData或文件内容加载到UIImage、用UIImagePNGRepresentation重新提取数据并将其保存回NSData的过程将从图像中删除元数据。 不过,这种简单的技术也有其缺点。特别要注意的是,强迫它使用PNG表示的过程可能会极大地影响输出NSData的大小。例如,如果原始图像是压缩的JPEG (例如由摄像机捕获),则生成的PNG文件实际上可以大于原始的JPEG。 通常,我倾向于获取原始数据(如果文档或包中的文件直接加载到NSData;如果是从ALAssetsLibrary检索的东西,则检索ALAsset,以及从ALAssetRepresentation中检索,然后使用getBytes获取原始资产的原始二进制表示)。这样就避免了通过UIImage (特别是在随后使用UIImagePNGRepresentationUIImageJEPGRepresentation)进行往返操作。
  2. 如果要删除exif数据,可以:
代码语言:javascript
运行
复制
- Create an image source from the original `NSData`;
- Create an image destination, using the same "number of images" (almost always 1) and the "type";
- 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).

因此,它看起来可能如下:

  • (NSData *)dataByRemovingExif:(NSData *)数据{ CGImageSourceRef源=CGImageSourceCreateWithData((CFDataRef)数据,NULL);NSMutableData *mutableData =零;if (源){ CFStringRef类型=CGImageSourceGetType(源);size_t计数=CGImageSourceGetCount(源);mutableData = NSMutableData数据;CGImageDestinationRef目的=dataByRemovingExif类型、计数、NULL);(Id) CGImageDestinationAddImageFromSource(destination,:(Id)kCGImagePropertyExifDictionary:(id)kCFNull,(id)kCGImagePropertyGPSDictionary:(id)kCFNull};if (目的){ for (size_t索引= 0;index < count;index++) {size_t源,索引,(__bridge CFDictionaryRef)removeExifProperties);} if (!CGImageDestinationFinalize(目的)){ NSLog(@"CGImageDestinationFinalize failed");}CFRelease(目的地);}CFRelease(源);}返回mutableData;} 注意,GPS信息在技术上不是exif数据,但我假设您也想删除它。如果您想保存GPS数据,请从我的kCGImagePropertyGPSDictionary字典中删除removeExifProperties条目。
  1. 顺便说一句,在提取元数据的代码中,您似乎将CGImageMetadataRef转换为NSDictionary。如果您的技术有效,这很好,但我认为CGImageMetadataRef被认为是一种不透明的数据类型,而实际上应该使用CGImageMetadataCopyTags提取标记数组:
  • (NSArray *)metadataForData:(NSData *)数据{ NSArray *元数据阵列=零;CGImageSourceRef源=CGImageSourceCreateWithData((CFDataRef)数据,NULL);if (源){ CGImageMetadataRef元数据=CGImageSourceCopyMetadataAtIndex(源元数据,0,NULL);if (元数据){ metadataArray =CGImageSourceRef CFRelease(元数据);}CFRelease(源数据);}返回metadataArray;}} 为了完整起见,在7.0之前的iOS版本中,您可以从属性中提取数据:
  • (NSDictionary *)metadataForData:(NSData *)data { NSDictionary *properties =0;CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data,NULL);if (source) { properties =NSDictionary 0,NULL);CFRelease(源);}返回属性};
票数 14
EN

Stack Overflow用户

发布于 2014-08-31 05:42:41

根据图像I/O编程指南,您可以使用CGImageDestinationSetProperties添加属性的CFDictionaryRef

它们的示例代码是:

代码语言:javascript
运行
复制
float compression = 1.0; // Lossless compression if available.
int orientation = 4; // Origin is at bottom, left.
CFStringRef myKeys[3];
CFTypeRef   myValues[3];
CFDictionaryRef myOptions = NULL;
myKeys[0] = kCGImagePropertyOrientation;
myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
myKeys[1] = kCGImagePropertyHasAlpha;
myValues[1] = kCFBooleanTrue;
myKeys[2] = kCGImageDestinationLossyCompressionQuality;
myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
                      &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Release the CFNumber and CFDictionary objects when you no longer need them.

我不明白他们为什么不一路上拿走它。我猜接下来会是:

  • 创建一个CFImageDestinationRef
  • 把你的图像复制到上面
  • 在上面设置您想要的元数据

从文档中看,如何执行第一步并不是很清楚。因此,我查看了参考文献,它看起来可以这样做(没有测试):

代码语言:javascript
运行
复制
NSMutableData* mutableData = [[NSMutableData alloc] initWithCapacity:[pngData length]];
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge_transfer CFMutableDataRef)mutableData, <# Some UTI Type #>, 1, NULL);
CGImageDestinationAddImage(imageDestination, image, yourProperties);

CGImageDestinationFinalize(imageDestination);

因此,按照Apple在文档中显示的方式创建您的属性字典,然后创建一个图像目的地并将所有内容写入其中,包括您的属性。之后,您可以访问NSMutableData对象并读取图像数据。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25589118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档