IOS: 使用imageIO獲取和修改圖片的exif信息
使用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信息實現的。還有很多其他的信息,感興趣的可以自己寫個程序研究研究,這里就不展開了。
二、修改圖片exif信息
我們除了可以通過CGImageSourceRef讀取圖片信息,還可以通過CGImageDestinationRef來創建圖片文件,在創建的時候我們可以指定很多信息。例如我們可以通過CGImageDestinationRef來修改現有圖片的GPS信息,圖片方向,甚至還可以自己寫一個制作gif的小工具。
這塊兒我做了個實驗,通過修改圖片信息的方向,來完成旋轉圖片的功能。原圖方向為1(exif方向),我修改為3。保存后發現圖片的確翻轉過來了。于是更進一步想著試一下看看能不能完成90°旋轉的功能,于是把圖片方向改為6,保存后發現通過UIImage加載的圖片顯示出現問題了,雖然方向是轉過來了,但是顯示卻被拉伸了。但是把保存后的圖片存到系統相冊,發現一切正常。
到底是哪塊兒出了問題呢?
我想了一下是不是應該在修改方向的同時修改一下圖片的pixelWidth和pixelHeight參數,于是滿心歡喜的嘗試了一下,結果還是UIImage加載出來還是拉伸顯示,導入系統相冊依舊正常。郁悶了到底是什么參數沒設置對呢?暫時還沒有什么思路,各路英雄要是有什么思路的話歡迎一起討論。
測試工程下載地址: https://github.com/smileEvday/SvImageInfo
測試工程中包含讀取圖片信息和修改圖片方向的工具類,以及簡單的測試代碼。上面修改圖片方向的那個問題還是沒有解決,希望路過的英雄能幫忙看看問題出在哪里,給點兒建議,謝謝。
注1: 文章中關于exif信息中圖片方向的知識主要參考國外一個博客JPEG Rotation and EXIF Orientation,真佩服他們研究問題的那種精神,寫的很細致,大家感興趣可以看看。
注2:轉載請著名出處,我的QQ: 1592232964,關于博客中提到的那個問題有任何好的建議歡迎聯系我,感激不盡?。。?/span>
??請樓主喝杯豆漿??
![]() |

浙公網安備 33010602011771號