使用ImageIO保留EXIF信息的图片
2016-01-14 14:24
381 查看
使用ImageIO上传保留EXIF信息的图片
相信大多数项目中需要上传图片,但是从相机中取到的图片再上传到服务器,一般的项目就是直接用NSData *data = UIImageJPEGRepresentation(image, 1)把图片压缩转换成DATA进行上传。然而在转成UIImage的时候,会把图片的EXIF一些信息自动隐藏,所以别人拿到你的图片别人是看不到这些信息的。所以我就在网上找到了以下的方法,主要借助ImageIO框架,先写入本地再进行上传。
stack overflow原文
ALAssetRepresentation *image_Representation = [asset defaultRepresentation]; // create a buffer to hold image data uint8_t *buffer = (Byte *)malloc(image_Representation.size); NSUInteger length = [image_Representation getBytes:buffer fromOffset:0.0 length:image_Representation.size error:nil]; if (length != 0) { // buffer -> NSData object; free buffer afterwards NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:image_Representation.size freeWhenDone:YES]; // identify image type (jpeg, png, RAW file, ...) using UTI hint float compression = 0.0; int orientation = 4; NSDictionary *sourceOptionsDict = @{(__bridge id)kCGImageSourceTypeIdentifierHint:[image_Representation UTI], (__bridge id)kCGImageDestinationLossyCompressionQuality: (__bridge id)CFNumberCreate(NULL, kCFNumberFloatType, &compression), (__bridge id)kCGImagePropertyOrientation:(__bridge id)CFNumberCreate(NULL, kCFNumberIntType, &orientation), (__bridge id)kCGImagePropertyHasAlpha:(__bridge id)kCFBooleanTrue}; // create CGImageSource with NSData CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)adata, (__bridge CFDictionaryRef)sourceOptionsDict); // get imagePropertiesDictionary CFDictionaryRef imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(sourceRef,0, NULL); // get exif data CFDictionaryRef exif = (CFDictionaryRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyExifDictionary); NSDictionary *exif_dict = (__bridge NSDictionary*)exif; NSLog(@"exif_dict: %@",exif_dict); // save image WITH meta data CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, imagePropertiesDictionary); //存入本地 NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSURL *fileURL = nil; if (![[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] isEqualToString:@"public.tiff"]) { fileURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.%@", documentsDirectory, @"myimage", [[[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] componentsSeparatedByString:@"."] objectAtIndex:1] ]]; CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((__bridge CFURLRef)fileURL, (__bridge CFStringRef)[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"], 1, NULL ); CGImageDestinationAddImage(dr, imageRef, imagePropertiesDictionary); CGImageDestinationFinalize(dr); CFRelease(dr); NSData *imageData = [NSData dataWithContentsOfURL:fileURL]; // NSLog(@"%lu",(unsigned long)imageData.length); [blockSelf.selectedPhotos addObject:imageData]; }else { NSLog(@"no valid kCGImageSourceTypeIdentifierHint found …"); } // clean up CFRelease(imageRef); CFRelease(imagePropertiesDictionary); CFRelease(sourceRef); }else { NSLog(@"image_representation buffer length == 0"); }
然而你会发现这里比原文多了一点。
原图太大,上传辣么大的图,慢,费流量,所以需要就原图进行压缩。如果想要对原图进行压缩,就需要在
sourceOptionsDict这个字典中添加
kCGImageDestinationLossyCompressionQuality这个KEY对应的VALUE为
CFNumber此值0.0~1.0.如此添加之后,我以为就OK了,然而并没有什么卵用,原图是多大,压缩后还是多大。思前想后,我觉得一定是一些属性对压缩产生了冲突,于是我就查阅了苹果官方文档,发现没什么大的改变,也就是字典那的一些转换。那就用官方的试试…
ALAssetRepresentation *image_Representation = [asset defaultRepresentation]; float compression = 0; // 压缩比例 int orientation = 1; // 方向 CFStringRef myKeys[4]; CFTypeRef myValues[4]; 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); myKeys[3] = kCGImageSourceTypeIdentifierHint; myValues[3] = (__bridge CFTypeRef)([image_Representation UTI]); myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); //创建DATA uint8_t *buffer = (Byte *)malloc(image_Representation.size); NSUInteger length = [image_Representation getBytes:buffer fromOffset:0.0 length:image_Representation.size error:nil]; NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:image_Representation.size freeWhenDone:YES]; /*********构建CGImageRef*******/ //CGImageSourceCreateWithData CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)adata, myOptions); CFDictionaryRef imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(sourceRef,0, NULL); CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, imagePropertiesDictionary); /*********构建文件URL*******/ NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *imageType = [(__bridge NSDictionary *)myOptions objectForKey:@"kCGImageSourceTypeIdentifierHint"]; NSURL *fileURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.%@", documentsDirectory, @"myimage", [[imageType componentsSeparatedByString:@"."] objectAtIndex:1] ]]; [blockSelf writeCGImage:imageRef toURL:fileURL withType:(__bridge CFStringRef)(imageType) andOptions:myOptions]; - (void)writeCGImage: (CGImageRef) image toURL: (NSURL*) url withType: (CFStringRef) imageType andOptions: (CFDictionaryRef) options { CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((CFURLRef)url, imageType, 1, NULL);//此处NULL不能为nil,否则图片为空 CGImageDestinationAddImage(myImageDest, image, options); CGImageDestinationFinalize(myImageDest); CFRelease(myImageDest); }
如此改变之后,就成功的压缩了图片,上传的时候直接取到图片转成Data然后进行上传。
然而对比了使用ImageIO与使用UIImage的方法之后会发现,还是使用
UIImageJPEGRepresentation进行压缩得到的图片更小一些,这需要根据项目而定采用哪种方式。
相关文章推荐
- ios 2015年App Store审核被拒的23个理由(附官方邮件原文)
- 应用本地化
- C#实现百度站长工具链接主动提交功能
- 远离人人网
- 护照办理流程
- 香港城市大学交换生手续办理经历
- 推荐文本编辑器GVIM
- 迅雷下载链接解码
- 关于A left join B,A是否一定是主表?
- java--邮箱的正则表达式匹配
- [转载]史上最强的.vimrc文件
- 修改hosts文件上facebook
- 今天在网上拼凑的.vimrc文件
- 博客和微博
- 其实我是来吐槽windows的
- 抓取网页数据的小程序
- [转载]JAVA开发八荣八耻
- 一晃也已经两年了
- Fedora19添加桌面系统,实现类似windows桌面
- 程序猿装B指南