我正在开发相机应用程序。我想追加DateTimeOriginal& DateTimeDigitized为exif元数据。我已经创建了Swift类来获取和保存Exif。
import ImageIO
extension NSData {
func exifNSDict() -> NSDictionary? {
return _exifCFDict() as NSDictionary?
}
func exifCFDict() -> CFDictionaryRef? {
return _exifCFDict()
}
func imageNSUTI() -> NSString? {
return _imageUTI() as NSString?
}
func imageCFUTI() -> CFStringRef? {
return _imageUTI()
}
func appendExif(exif: CFDictionaryRef) -> NSData? {
return _appendExif(exif)
}
}
//MARK: - Private
extension NSData {
private func _exifCFDict() -> CFDictionaryRef? {
//1.(a) Create original image source ref
let imageSource: CGImageSourceRef? = CGImageSourceCreateWithData(self, nil)
if imageSource == nil {
return nil
}
//1.(b) Get image properties
let imageProperties: CFDictionaryRef? = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil)
if imageProperties == nil {
return nil
}
//1.(b) Get original exif
let dictKey = unsafeBitCast(kCGImagePropertyExifDictionary, UnsafePointer<Void>.self)
let exif: CFDictionaryRef? = unsafeBitCast(CFDictionaryGetValue(imageProperties, dictKey), CFDictionaryRef.self)
if exif == nil {
return nil
}
return exif
}
private func _imageUTI() -> CFStringRef? {
let imageSource: CGImageSourceRef? = CGImageSourceCreateWithData(self, nil)
if imageSource == nil {
return nil
}
let imageUTI: CFStringRef? = CGImageSourceGetType(imageSource!)
return imageUTI
}
private func _appendExif(exif: CFDictionaryRef) -> NSData? {
//writing both original image data and mutable exif back to a destination
let imageSource: CGImageSourceRef? = CGImageSourceCreateWithData(self, nil)
if imageSource == nil {
return nil
}
let imageUTI: CFStringRef? = CGImageSourceGetType(imageSource!)
if imageUTI == nil {
return nil
}
//3. create a mutable data object to which the originalImageData and exif dictionary will be written.
let finalCombinedData = NSMutableData()
//4. create a destination object where the whole thing needs to be written
let destination : CGImageDestinationRef? = CGImageDestinationCreateWithData(finalCombinedData, imageUTI!, 1, nil)
if destination == nil {
return nil
}
//5. This is the actual method that does the writing.
CGImageDestinationAddImageFromSource(destination!, imageSource!, 0, exif);
//6. Commit the writing
let success = CGImageDestinationFinalize(destination!);
if !success {//error
return nil
}
return finalCombinedData.copy() as? NSData
}
}
现在我可以通过调用exifCFDict
来获取exifCFDictionaryRef exif = [imageData exifCFDict];
然后我从这个CFDictionaryRef创建了一个MutableCFDictionaryRef,并为kCGImagePropertyExifDateTimeOriginal和kCGImagePropertyExifDateTimeDigitized附加了如下值:
1.(b) Convert original exif to mutable exif
CFMutableDictionaryRef mutableExif = CFDictionaryCreateMutableCopy(NULL, 0, exif);
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy:MM:dd HH:mm:ss"];
NSString *nowDateStr = [formatter stringFromDate:[[NSDate alloc] init]];
CFDictionarySetValue(mutableExif, kCGImagePropertyExifDateTimeOriginal, (__bridge const void *)nowDateStr);
CFDictionarySetValue(mutableExif, kCGImagePropertyExifDateTimeDigitized, (__bridge const void *)nowDateStr);
我可以在可变副本中看到kCGImagePropertyExifDateTimeOriginal和kCGImagePropertyExifDateTimeDigitized。 然后我尝试通过调用上面类别中的appendExif函数将这个可变字典写入imageData。
//append exif to originalImageData
NSData *imageDataWithExif = [imageData appendExif:mutableExif];
然而,当我试图从imageDataWithExif获取exif时,我意识到kCGImagePropertyExifDateTimeOriginal&amp;缺少kCGImagePropertyExifDateTimeDigitized。所有其他信息都存在。
经过一番打击和尝试后,我找到了解决方法。如果不是为exif创建一个可变副本,我只是附加了kCGImagePropertyExifDateTimeDigitized&amp; kCGImagePropertyExifDateTimeOriginal to原始Exif从Image Data中获取,然后如果我将此原始exif传递给appendExif函数,则kCGImagePropertyExifDateTimeOriginal和kCGImagePropertyExifDateTimeDigitized将出现在新的imageData中。
CFDictionarySetValue(exif, kCGImagePropertyExifDateTimeOriginal, (__bridge const void *)nowDateStr);
CFDictionarySetValue(exif, kCGImagePropertyExifDateTimeDigitized, (__bridge const void *)nowDateStr);
//append exif to originalImageData
NSData *imageDataWithExif = [imageData exif];
这解决了我现在的问题,但这种解决方法让我感到困惑。
P.S。我对IOS开发还很陌生。