1.Exif简介
可交换图像文件格式常被简称为Exif(Exchangeable image file format),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
Exif可以附加于JPEG、TIFF、RIFF、EXIF、GPS等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。
Exif信息以0xFFE1作为开头标记,后两个字节表示Exif信息的长度。所以Exif信息最大为64 kB,而内部采用TIFF格式。
2.读取Exif信息
Exif信息是通过ImageIO框架来实现的,ImageIO框架在iOS中偏低层,所以提供的接口都是C风格的,关键数据也都是使用CoreFoundation进行存储。进行数据的操作也就需要CoreFoundation和上层Foundation之间进行桥接转换。
1. 获取图片文件
NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"YourPic" withExtension:@""];
2.创建CGImageSourceRef
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)fileUrl, NULL);
3.利用imageSource获取全部ExifData
CFDictionaryRef imageInfo = CGImageSourceCopyPropertiesAtIndex(imageSource, 0,NULL);
4.从全部ExifData中取出EXIF文件
NSDictionary *exifDic = (__bridge NSDictionary *)CFDictionaryGetValue(imageInfo, kCGImagePropertyExifDictionary) ;
5.打印全部Exif信息及EXIF文件信息
NSLog(@"All Exif Info:%@",imageInfo);
NSLog(@"EXIF:%@",exifDic);
一张佳能相机拍摄的照片中的Exif信息:
All Exif Info:{
ColorModel = RGB;
DPIHeight = 200;
DPIWidth = 200;
Depth = 8;
Orientation = 1;
PixelHeight = 667;
PixelWidth = 1000;
ProfileName = "sRGB IEC61966-2.1";
"{Exif}" = {
ApertureValue = "3.375";
BodySerialNumber = 214014001512;
ColorSpace = 1;
ComponentsConfiguration = (
1,
2,
3,
0
);
CustomRendered = 0;
DateTimeDigitized = "2016:07:05 16:12:02";
DateTimeOriginal = "2016:07:05 16:12:02";
ExifVersion = (
2,
3
);
ExposureBiasValue = 0;
ExposureMode = 0;
ExposureProgram = 3;
ExposureTime = "0.0004";
FNumber = "3.2";
Flash = 16;
FlashPixVersion = (
1,
0
);
FocalLength = 168;
FocalPlaneResolutionUnit = 2;
FocalPlaneXResolution = "3545.827586206897";
FocalPlaneYResolution = "3526.530612244898";
ISOSpeedRatings = (
400
);
LensMake = "Canon 35mm f1.4";
LensModel = "2016/09/21 11:04:31";
LensSerialNumber = 0000c08f5f;
LensSpecification = (
70,
200,
0,
0
);
MeteringMode = 3;
PixelXDimension = 1000;
PixelYDimension = 667;
RecommendedExposureIndex = 400;
SceneCaptureType = 0;
SensitivityType = 2;
ShutterSpeedValue = "11.375";
SubsecTime = 795;
SubsecTimeDigitized = 30;
SubsecTimeOriginal = 30;
WhiteBalance = 0;
};
"{IPTC}" = {
DateCreated = 20160705;
DigitalCreationDate = 20160705;
DigitalCreationTime = 161202;
TimeCreated = 161202;
};
"{JFIF}" = {
DensityUnit = 0;
JFIFVersion = (
1,
0,
1
);
XDensity = 200;
YDensity = 200;
};
"{TIFF}" = {
DateTime = "2016:07:08 16:45:32";
Make = Canon;
Model = "Canon EOS-1D X";
Orientation = 1;
ResolutionUnit = 2;
Software = "ACDSee Pro 8";
XResolution = 200;
YResolution = 200;
};
}
3.写入Exif信息
1. 获取图片中的EXIF文件和GPS文件
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"YourImage"], 1);
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
NSDictionary *imageInfo = (__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
NSMutableDictionary *metaDataDic = [imageInfo mutableCopy];
NSMutableDictionary *exifDic =[[metaDataDic objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
NSMutableDictionary *GPSDic =[[metaDataDic objectForKey:(NSString*)kCGImagePropertyGPSDictionary]mutableCopy];
2. 修改EXIF文件和GPS文件中的部分信息
[exifDic setObject:[NSNumber numberWithFloat:1234.3] forKey:(NSString *)kCGImagePropertyExifExposureTime];
[exifDic setObject:@"SenseTime" forKey:(NSString *)kCGImagePropertyExifLensModel];
[GPSDic setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
[GPSDic setObject:[NSNumber numberWithFloat:116.29353] forKey:(NSString*)kCGImagePropertyGPSLatitude];
[metaDataDic setObject:exifDic forKey:(NSString*)kCGImagePropertyExifDictionary];
[metaDataDic setObject:GPSDic forKey:(NSString*)kCGImagePropertyGPSDictionary];
3. 将修改后的文件写入至图片中
CFStringRef UTI = CGImageSourceGetType(source);
NSMutableData *newImageData = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)newImageData, UTI, 1,NULL);
//add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metaDataDic);
CGImageDestinationFinalize(destination);
4. 保存图片
NSString *directoryDocuments = NSTemporaryDirectory();
[newImageData writeToFile: directoryDocuments atomically:YES];
5. 查看修改后图片的Exif信息
CIImage *testImage = [CIImage imageWithData:newImageData];
NSDictionary *propDict = [testImage properties];
NSLog(@"Properties %@", propDict);
修改后的Exif信息:
Properties {
ColorModel = RGB;
Depth = 8;
Orientation = 1;
PixelHeight = 667;
PixelWidth = 1000;
ProfileName = "sRGB IEC61966-2.1";
"{Exif}" = {
ColorSpace = 1;
ExposureTime = "1234.3";
LensModel = SenseTime;
PixelXDimension = 1000;
PixelYDimension = 667;
};
"{GPS}" = {
Latitude = "116.2935333333333";
LatitudeRef = N;
};
"{JFIF}" = {
DensityUnit = 0;
JFIFVersion = (
1,
0,
1
);
XDensity = 72;
YDensity = 72;
};
"{TIFF}" = {
Orientation = 1;
};
}
4.注意事项
关于无法修改Exif值的几点注意事项:
1. 传入的数据格式与Exif规定的不符
Exif的每条信息都有对应的数据类型,如:String Float... 如果数据类型传入错误将无法写入文件。
2. 传入的字段超过规定字段长度
3. 相互依赖的字段只添加了一个字段
在GPS文件中经纬度的度数的字段与经纬度的方向的字段相互依赖,修改经/纬度数需要经/纬方向字段的存在,否则修改无效。
5.外部链接
- Exif2.3官方文档
- Introduction to UTI Overview
- Modified EXIF data doesn't save properly