Быстрый доступ к словарю EXIF

Информация: использование Swift и функции CGImageSourceCreateWithURL.

Я пытаюсь загрузить файл с URL-адреса, а затем отредактировать словарь, в котором есть все данные с этой конкретной фотографии.

Это код из файла .swift.

    let url = NSURL(string: "http://jwphotographic.co.uk/Images/1.jpg")
    let imageSource = CGImageSourceCreateWithURL(url, nil)
    let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as Dictionary

    println(imageProperties)

    //this is an example
    let aperture = imageProperties[kCGImagePropertyGPSLatitude] as! NSNumber!

    /*
    //these are all being defined as nil
    //Load the ones from the exif data of the file
    let lensUsed = imageProperties[kCGImagePropertyExifFocalLength]
    let aperture = imageProperties[kCGImagePropertyExifApertureValue] as!
    let isoSpeed = imageProperties[kCGImagePropertyExifISOSpeedRatings] as! NSNumber
    let latitude = imageProperties[kCGImagePropertyGPSLatitude] as! NSNumber
    let longitude = imageProperties[kCGImagePropertyGPSLongitude] as! NSNumber
    let shutterSpeed = imageProperties[kCGImagePropertyExifShutterSpeedValue] as! NSNumber
    let cameraName = imageProperties[kCGImagePropertyExifBodySerialNumber] as! NSNumber
    */

    println(aperture)

Несмотря на то, что свойства изображения печатают все данные, как и ожидалось, независимо от того, что я пытался извлечь из словаря imageProperties, оно всегда возвращается как ноль, например «диафрагма» в примере. ImageProperties печатается как;

[{TIFF}: {
     Artist = JOHN;
     Copyright = "[email protected]";
     DateTime = "2015:07:31 21:07:05";
     Make = Canon;
     Model = "Canon EOS 7D Mark II";
     ResolutionUnit = 2;
     Software = "Adobe Photoshop Lightroom 6.0 (Macintosh)";
     XResolution = 72;
     YResolution = 72;
}, {IPTC}: {
     Byline =     (
       JOHN
     );
     CopyrightNotice = etc.. etc..

Я провел много исследований и тестов, и я просто не могу понять, что я делаю неправильно, чтобы получить доступ к элементам в этом словаре. Может ли кто-нибудь привести мне пример, как я могу установить переменную как элемент «Модель» внутри словаря. ?


person user3423554    schedule 08.08.2015    source источник


Ответы (4)


В Swift 3.0 я нашел следующее решение

let url = NSURL(string: "http://jwphotographic.co.uk/Images/1.jpg")
let imageSource = CGImageSourceCreateWithURL(url, nil)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as Dictionary?
let exifDict = imageProperties?[kCGImagePropertyExifDictionary]

Теперь вы можете получить доступ к exif-тегам, например,

let dateTimeOriginal = exifDict?[kCGImagePropertyExifDateTimeOriginal]
Swift.print("dateTimeOriginal: \(dateTimeOriginal)")

Вы получите необязательные значения, и вам нужно проверить, есть ли значения или ноль. Список доступных констант свойств см. в документации Apple.

person Erich Kuester    schedule 12.01.2017

Чтобы получить параметры Exif, выполните следующие действия:

    let filePath_ = "file:///Users/pfernandes/Documents/softwareDevelopment/PhotoLine/TestData/IMG_1243.JPG"
    let fileURL = NSURL(string:filePath_)
    let myImage = CGImageSourceCreateWithURL(fileURL!,nil)

    let imageDict = CGImageSourceCopyPropertiesAtIndex(myImage!, 0, nil)! as NSDictionary;
    let tiffModel_ = imageDict.value(forKey: "{TIFF}")

    let cameraMake = (tiffModel_ as AnyObject).value(forKey: kCGImagePropertyTIFFMake as String)
    let cameraModel = (tiffModel_ as AnyObject).value(forKey: kCGImagePropertyTIFFModel as String)

    let exifDict_ = imageDict.value(forKey: "{Exif}") as! NSDictionary
    let dateTimeOriginal = exifDict_.value(forKey:kCGImagePropertyExifDateTimeOriginal as String) as! NSString
    let exposure         = exifDict_.value(forKey:kCGImagePropertyExifExposureTime as String)

    print ("\(String(describing: cameraMake)) \(String(describing: cameraModel)) \(dateTimeOriginal) \(exposure!)")
person Cortex    schedule 13.12.2015
comment
Есть ли способ получить информацию о камере из библиотеки фотографий? Спасибо - person ICL1901; 20.09.2017
comment
Да, я отредактировал свой ответ, чтобы показать пример того, как это сделать в последней версии Swift/Xcode. - person Cortex; 28.01.2018

Этот код поможет вам получить дату фото и exif

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true, completion: nil)
    if let image = info[.originalImage] as? UIImage {
        
       
        let assetURL = info[UIImagePickerController.InfoKey.referenceURL] as! NSURL
        let asset = PHAsset.fetchAssets(withALAssetURLs: [assetURL as URL], options: nil)
        guard let result = asset.firstObject else {
            return
        }

        let imageManager = PHImageManager.default()
        imageManager.requestImageData(for: result , options: nil, resultHandler:{
            (data, responseString, imageOriet, info) -> Void in
            let imageData: NSData = data! as NSData
            if let imageSource = CGImageSourceCreateWithData(imageData, nil) {
                let imageDict = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
                let exifDict_ = imageDict.value(forKey: "{Exif}") as! NSDictionary
                   let dateTimeOriginal = exifDict_.value(forKey:kCGImagePropertyExifDateTimeOriginal as String) as! NSString
               print (" exifDict : \(exifDict_)")
                print (" fecha : original \(dateTimeOriginal)")
            }
        })
        
    picker.dismiss(animated: true, completion: nil)
}
person Marin Espinoza    schedule 26.11.2020

Вот пример кода, который помогает нам прочитать все метаданные изображения и преобразовать их в формат словаря.

        guard let imageSource = CGImageSourceCreateWithURL(fileURL as CFURL, nil),
              let metadata = CGImageSourceCopyMetadataAtIndex(imageSource, 0, nil),
              let tags = CGImageMetadataCopyTags(metadata),
              let imageInfo = self.readMetadataTagArr(tagArr: tags) else { return }

Затем есть несколько вспомогательных функций, которые фактически выполняют всю тяжелую работу по извлечению/преобразованию данных в формат словаря.

    /// Reads the Arrays of tags and convert them into a dictionary of [String: Any]
private static func readMetadataTagArr(tagArr: CFArray) -> [String: Any]? {
    var result = [String: Any]()
    for (_, tag) in (tagArr as NSArray).enumerated() {
        let tagMetadata = tag as! CGImageMetadataTag
        if let cfName = CGImageMetadataTagCopyName(tagMetadata) {
            let name = String(cfName)
            result[name] = self.readMetadataTag(metadataTag: tagMetadata)
        }
    }
    return result
}

    /// convert CGImageMetadataTag to a dictionary of [String: Any]
private static func readMetadataTag(metadataTag: CGImageMetadataTag) -> [String: Any] {
    var result = [String: Any]()
    guard let cfName = CGImageMetadataTagCopyName(metadataTag) else { return result }
    let name = String(cfName)
    let value = CGImageMetadataTagCopyValue(metadataTag)
    
    /// checking the type of `value` object and then performing respective operation on `value`
    if CFGetTypeID(value) == CFStringGetTypeID() {
        let valueStr = String(value as! CFString)
        result[name] = valueStr
    } else if CFGetTypeID(value) == CFDictionaryGetTypeID() {
        let nsDict: NSDictionary = value as! CFDictionary
        result[name] = self.getDictionary(from: nsDict)
    } else if CFGetTypeID(value) == CFArrayGetTypeID() {
        let valueArr: NSArray = value as! CFArray
        for (_, item) in valueArr.enumerated() {
            let tagMetadata = item as! CGImageMetadataTag
            result[name] = self.readMetadataTag(metadataTag: tagMetadata)
        }
    } else {
        // when the data was of some other type
        let descriptionString: CFString = CFCopyDescription(value);
        let str = String(descriptionString)
        result[name] = str
    }
    return result
}

    /// Converting CGImage Metadata dictionary to [String: Any]
private static func getDictionary(from nsDict: NSDictionary) -> [String: Any] {
    var subDictionary = [String: Any]()
    for (key, val) in nsDict {
        guard let key = key as? String else { continue }
        let tempDict: [String: Any] = [key: val]
        if JSONSerialization.isValidJSONObject(tempDict) {
            subDictionary[key] = val
        } else {
            let mData = val as! CGImageMetadataTag
            let tempDict: [String: Any] = [key: self.readMetadataTag(metadataTag: mData)]
            if JSONSerialization.isValidJSONObject(tempDict) {
                subDictionary[key] = tempDict
            }
        }
    }
    return subDictionary
}

Вот список всех извлеченных ключей словаря Вот список всех извлеченных ключей словаря

Вот несколько примеров значений словаря Вот некоторые примеры значений из словаря

person Hassaan Fayyaz    schedule 21.04.2021