将 EXIF 数据保存为 JPEG - Swift
Saving EXIF data to JPEG - Swift
我目前正在尝试使用 UIImagePickerController 在应用程序中拍摄照片,将它们保存到本地数据库并稍后上传到服务。
但是元数据(尤其是 EXIF)似乎没有自动与这张图片捆绑在一起。我试过像这样提取它:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
self.imageDelegate?.saveImage( image: info[UIImagePickerControllerOriginalImage] as! UIImage, metadata: (info[UIImagePickerControllerMediaMetadata] as? NSDictionary)! )
// ...
}
现在我应该有图像和元数据了,但是我怎样才能将它存储到 JPEG 文件中呢?我需要服务器上图片中的GPS数据。
我目前正在直接从相机胶卷的 UImage 创建图像:
UIImageJPEGRepresentation(image,CGFloat(Constants.JPEG_QUALITY))
这将被存储和上传。
我读到过可能会使用“CGImageDestination”,但我不知道如何在我的案例中使用它们。
我的解决方案:
func toJpegWithExif(image: UIImage, metadata: NSDictionary, location: CLLocation?) -> Data? {
return autoreleasepool(invoking: { () -> Data in
let data = NSMutableData()
let options = metadata.mutableCopy() as! NSMutableDictionary
options[ kCGImageDestinationLossyCompressionQuality ] = CGFloat(Constants.JPEG_QUALITY)
// if location is available, add GPS data, thanks to https://gist.github.com/nitrag/343fe13f01bb0ef3692f2ae2dfe33e86
if ( nil != location ) {
let gpsData = NSMutableDictionary()
let altitudeRef = Int(location!.altitude < 0.0 ? 1 : 0)
let latitudeRef = location!.coordinate.latitude < 0.0 ? "S" : "N"
let longitudeRef = location!.coordinate.longitude < 0.0 ? "W" : "E"
// GPS metadata
gpsData[(kCGImagePropertyGPSLatitude as String)] = abs(location!.coordinate.latitude)
gpsData[(kCGImagePropertyGPSLongitude as String)] = abs(location!.coordinate.longitude)
gpsData[(kCGImagePropertyGPSLatitudeRef as String)] = latitudeRef
gpsData[(kCGImagePropertyGPSLongitudeRef as String)] = longitudeRef
gpsData[(kCGImagePropertyGPSAltitude as String)] = Int(abs(location!.altitude))
gpsData[(kCGImagePropertyGPSAltitudeRef as String)] = altitudeRef
gpsData[(kCGImagePropertyGPSTimeStamp as String)] = location!.timestamp.isoTime()
gpsData[(kCGImagePropertyGPSDateStamp as String)] = location!.timestamp.isoDate()
gpsData[(kCGImagePropertyGPSVersion as String)] = "2.2.0.0"
options[ kCGImagePropertyGPSDictionary as String ] = gpsData
}
let imageDestinationRef = CGImageDestinationCreateWithData(data as CFMutableData, kUTTypeJPEG, 1, nil)!
CGImageDestinationAddImage(imageDestinationRef, image.cgImage!, options)
CGImageDestinationFinalize(imageDestinationRef)
return data as Data
})
}
extension Date {
func isoDate() -> String {
let f = DateFormatter()
f.timeZone = TimeZone(abbreviation: "UTC")
f.dateFormat = "yyyy:MM:dd"
return f.string(from: self)
}
func isoTime() -> String {
let f = DateFormatter()
f.timeZone = TimeZone(abbreviation: "UTC")
f.dateFormat = "HH:mm:ss.SSSSSS"
return f.string(from: self)
}
}
该方法将 UIImage 转换为 Jpeg,其中包含来自相机的 EXIF 数据以及来自 CLLocationManager 的可选 GPS 位置。
我目前正在尝试使用 UIImagePickerController 在应用程序中拍摄照片,将它们保存到本地数据库并稍后上传到服务。
但是元数据(尤其是 EXIF)似乎没有自动与这张图片捆绑在一起。我试过像这样提取它:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
self.imageDelegate?.saveImage( image: info[UIImagePickerControllerOriginalImage] as! UIImage, metadata: (info[UIImagePickerControllerMediaMetadata] as? NSDictionary)! )
// ...
}
现在我应该有图像和元数据了,但是我怎样才能将它存储到 JPEG 文件中呢?我需要服务器上图片中的GPS数据。
我目前正在直接从相机胶卷的 UImage 创建图像:
UIImageJPEGRepresentation(image,CGFloat(Constants.JPEG_QUALITY))
这将被存储和上传。
我读到过可能会使用“CGImageDestination”,但我不知道如何在我的案例中使用它们。
我的解决方案:
func toJpegWithExif(image: UIImage, metadata: NSDictionary, location: CLLocation?) -> Data? {
return autoreleasepool(invoking: { () -> Data in
let data = NSMutableData()
let options = metadata.mutableCopy() as! NSMutableDictionary
options[ kCGImageDestinationLossyCompressionQuality ] = CGFloat(Constants.JPEG_QUALITY)
// if location is available, add GPS data, thanks to https://gist.github.com/nitrag/343fe13f01bb0ef3692f2ae2dfe33e86
if ( nil != location ) {
let gpsData = NSMutableDictionary()
let altitudeRef = Int(location!.altitude < 0.0 ? 1 : 0)
let latitudeRef = location!.coordinate.latitude < 0.0 ? "S" : "N"
let longitudeRef = location!.coordinate.longitude < 0.0 ? "W" : "E"
// GPS metadata
gpsData[(kCGImagePropertyGPSLatitude as String)] = abs(location!.coordinate.latitude)
gpsData[(kCGImagePropertyGPSLongitude as String)] = abs(location!.coordinate.longitude)
gpsData[(kCGImagePropertyGPSLatitudeRef as String)] = latitudeRef
gpsData[(kCGImagePropertyGPSLongitudeRef as String)] = longitudeRef
gpsData[(kCGImagePropertyGPSAltitude as String)] = Int(abs(location!.altitude))
gpsData[(kCGImagePropertyGPSAltitudeRef as String)] = altitudeRef
gpsData[(kCGImagePropertyGPSTimeStamp as String)] = location!.timestamp.isoTime()
gpsData[(kCGImagePropertyGPSDateStamp as String)] = location!.timestamp.isoDate()
gpsData[(kCGImagePropertyGPSVersion as String)] = "2.2.0.0"
options[ kCGImagePropertyGPSDictionary as String ] = gpsData
}
let imageDestinationRef = CGImageDestinationCreateWithData(data as CFMutableData, kUTTypeJPEG, 1, nil)!
CGImageDestinationAddImage(imageDestinationRef, image.cgImage!, options)
CGImageDestinationFinalize(imageDestinationRef)
return data as Data
})
}
extension Date {
func isoDate() -> String {
let f = DateFormatter()
f.timeZone = TimeZone(abbreviation: "UTC")
f.dateFormat = "yyyy:MM:dd"
return f.string(from: self)
}
func isoTime() -> String {
let f = DateFormatter()
f.timeZone = TimeZone(abbreviation: "UTC")
f.dateFormat = "HH:mm:ss.SSSSSS"
return f.string(from: self)
}
}
该方法将 UIImage 转换为 Jpeg,其中包含来自相机的 EXIF 数据以及来自 CLLocationManager 的可选 GPS 位置。