iOS獲取照片EXif資訊
方法一:知道照片URL
//新建CGImageSourceRef物件
CGImageSourceRef*imageRef= CGImageSourceCreateWithURL((CFURLRef)imageUrl, NULL);
//獲取照片資訊
NSDictionary*imageProperty=(NSDictionary*)CGImageSourceCopyPropertiesAtIndex(_imageRef, 0, NULL);
//獲取照片EXIF資訊
NSDictionary*ExifDictionary= [imagePropertyvalueForKey:(NSString*)kCGImagePropertyExifDictionary];
方法二:從UIimage中獲取
//將UIimage轉換為NSData
NSData *imageData=UIImageJPEGRepresentation(self.currentPhoto.image, 1.0);
//將NSData轉換為CFDataRef並新建CGImageSourceRef物件
CGImageSourceRefimageRef=CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
NSDictionary*imageProperty=(NSDictionary*)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(imageRef,0, NULL));
NSDictionary*ExifDictionary=[imagePropertyvalueForKey:(NSString*)kCGImagePropertyExifDictionary];
使用imageIO獲取圖片的exif資訊
一幅圖片除了包含我們能看見的畫素資訊,背後還包含了拍攝時間,光圈大小,曝光等資訊。UIImage類將這些細節資訊都隱藏了起來,只提供我們關心的圖片尺寸,圖片方向等。我們可以通過imageIO框架獲取到圖片背後的所有資訊,下面就讓我們一起看看。
imageIO框架是iOS中偏底層一點兒的框架,它內部提供的介面都是C風格的,關鍵資料也都是使用CoreFoundation進行儲存。慶幸的是CoreFoundation中有很多資料型別都可以上層的資料Foundation框架中的資料型別進行無縫橋接。這也就大大方便了我們對圖片資訊的操作。
CGImageSourceRef是整個imageIO的入口,通過它我們可以完成從檔案的載入圖片。載入完成以後我們就得到一個CGImageSourceRef,通過CGImageSourceRef我們就可以獲取圖片檔案的大小,UTI(uniform type identifier),內部包含幾張圖片,訪問每一張圖片以及獲取每張圖片對應的exif資訊等。
你可能會有一個疑問,為什麼會有幾張圖片呢?
這塊兒我解釋一下,imageSourceRef和檔案是一一對應的,通常我們見到的圖片檔案(例如jpg,png)內部都只有一張圖片,這種情況我們通過CGImageSourceGetCount方法得到的就會是1。但是不能排除一個圖片檔案中會有多種圖片的情況,例如gif檔案,這個時候一個檔案中就可能包含幾張甚至幾十張圖片。前面我寫的一片部落格《IOS中如何解析並顯示Gif》就是通過imageSource實現載入和解析gif的功能。
下面是系統相機拍的照片的exif資訊:
複製程式碼
程式碼如下:
image property: {
ColorModel = RGB;
DPIHeight = 72;
DPIWidth = 72;
Depth = 8;
Orientation = 6;
PixelHeight = 2448;
PixelWidth = 3264;
"{Exif}" = {
ApertureValue = "2.526069";
BrightnessValue = "-0.5140446";
ColorSpace = 1;
ComponentsConfiguration = (
1,
2,
3,
0
);
DateTimeDigitized = "2013:06:24 22:11:30";
DateTimeOriginal = "2013:06:24 22:11:30";
ExifVersion = (
2,
2,
1
);
ExposureMode = 0;
ExposureProgram = 2;
ExposureTime = "0.06666667";
FNumber = "2.4";
Flash = 16;
FlashPixVersion = (
1,
0
);
FocalLenIn35mmFilm = 33;
FocalLength = "4.13";
ISOSpeedRatings = (
400
);
MeteringMode = 3;
PixelXDimension = 3264;
PixelYDimension = 2448;
SceneCaptureType = 0;
SensingMethod = 2;
ShutterSpeedValue = "3.906905";
SubjectArea = (
2815,
1187,
610,
612
);
WhiteBalance = 0;
};
"{GPS}" = {
Altitude = "27.77328";
AltitudeRef = 0;
Latitude = "22.5645";
LatitudeRef = N;
Longitude = "113.8886666666667";
LongitudeRef = E;
TimeStamp = "14:11:23.36";
};
"{TIFF}" = {
DateTime = "2013:06:24 22:11:30";
Make = Apple;
Model = "iPhone 5";
Orientation = 6;
ResolutionUnit = 2;
Software = "6.1.4";
XResolution = 72;
YResolution = 72;
"_YCbCrPositioning" = 1;
};
}
從中我們可以看出最開始的幾項分別顯示了當前圖片的顏色模式,色深,x,y方向的DPI,實際畫素以及圖片的方向。我最開始看到這個方向時,心中一喜這不是UIImage中的imageOrientation,但是實驗發現這個方向和UIImage中的imageOrientation並不相等,此處的方向是exif標準定義的方向,從1到8分別對應這UIImage中的8個方向,只是順序不一樣,它們對應關係如下:
複製程式碼
程式碼如下:
enum {
exifOrientationUp = 1, // UIImageOrientationUp
exifOrientationDown = 3, // UIImageOrientationDown
exifOrientationLeft = 6, // UIImageOrientationLeft
exifOrientationRight = 8, // UIImageOrientationRight
// these four exifOrientation does not support by all camera, but IOS support these orientation
exifOrientationUpMirrored = 2, // UIImageOrientationUpMirrored
exifOrientationDownMirrored = 4, // UIImageOrientationDownMirrored
exifOrientationLeftMirrored = 5, // UIImageOrientationLeftMirrored
exifOrientationRightMirrored = 7, // UIImageOrientationRightMirrored
};
typedef NSInteger ExifOrientation;
目前市面上的大部分數碼相機和手機都會內建一個方向感應器,拍出的照片中會寫如方向資訊,但是通常都只會有前四種方向。這幾種Mirrored方向通常都是手機前置攝像頭自拍的時候才會設定。
exif為什麼要搞這麼一個方向呢?
幾乎所有的攝像頭在出場的時候成相晶片都是有方向的,拍出來的照片的畫素都是預設方向的。如果每拍一張照片就對這些畫素進行旋轉,如果數碼相機每秒連拍20張來算,旋轉操作將會非常耗時。更聰明的做法是拍照時只記錄一個方向,然後顯示的時候按方向顯示出來即可。因此exif定義了一個標準的方向引數,只要讀圖的軟體都來遵守規則,載入時候讀取圖片方向,然後做相應的旋轉即可。這樣既可以達到快速成像的目的,又能達到正確的顯示,何樂而不為呢。
常見的圖片瀏覽和編輯軟體都遵守這個規則,但是有一個我們最常用的看圖軟體(windows自帶的看圖程式)不會去讀這個方向,因此我們將數碼相機和手機拍出來的圖片匯入windows上時,會經常遇到方向錯誤的問題。不知道windows帝國是怎麼想的,或許和定義exif的組織有什麼過節吧。
圖片資訊中除了上面看提到的那些,還有拍攝的GPS資訊,iOS自帶的相簿軟體中的地點tab就是按照GPS資訊實現的。還有很多其他的資訊,感興趣的可以自己寫個程式研究研究,這裡就不展開了。