1. 程式人生 > >iOS獲取照片EXif資訊

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資訊實現的。還有很多其他的資訊,感興趣的可以自己寫個程式研究研究,這裡就不展開了。