添加GPS元数据字典到AVFoundation拍摄的图像 [英] add GPS metadata dictionary to image taken with AVFoundation in swift
问题描述
我试图在swift中用 AVFoundation
拍摄的图像添加GPS元数据。我有下面的代码粘贴,但它不工作。我的错误在哪里?
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let imgDataProvider = CGDataProviderCreateWithCFData(imageData);
let imageRef = CGImageCreateWithJPEGDataProvider(imgDataProvider,nil,true,.RenderingIntentDefault)
let properties = self.getImageProperties(imageData)
let mutableDictionary:NSMutableDictionary = NSMutableDictionary(dictionary:properties)
let newImageData = CFDataCreateMutable(nil,0)
let type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,image / jpgas CFString,kUTTypeImage)
let destination = CGImageDestinationCreateWithData(newImageData,(type?.takeRetainedValue())!, 1,nil)
CGImageDestinationAddImage(destination!,imageRef !, mutableDictionary)
CGImageDestinationFinalize(destination!)
let newImage = newImageData
getImageProperties方法:
private func getImageProperties(data:NSData) - > NSDictionary {
let imageSourceRef = CGImageSourceCreateWithData(data,nil);
let properties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef !, 0,nil)
let props = properties
return props!
}
getGPSDictionary方法:
private func getGPSDictionary() - > NSDictionary {
let dictionary = [kCGImagePropertyGPSLatitude as String:54,kCGImagePropertyGPSLongitude as String:23]
return dictionary
}
是的,我知道坐标硬编码到目前为止,但现在重要的是让它工作,我会更新位置。
这就是我做到的。这工作在Swift 2.2 iOS 9.2上。
$ b $ pre $ func shutter(sender:AnyObject){
let connection = imageOutput。 connectionWithMediaType(AVMediaTypeVideo)
//设置方向
如果connection.supportsVideoOrientation {
connection.videoOrientation = currentVideoOrientation()
}
imageOutput.captureStillImageAsynchronouslyFromConnection(connection){
(sampleBuffer:CMSampleBuffer!,error:NSError!) - >如果sampleBuffer!= nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
//获得旧的EXIF
let oldEXIF = self.getEXIFFromImage( imageData)
//将gps信息添加到旧的exif
let newEXIF = self.addGPSToEXIF(oldEXIF,new:self.getGPSDictionaryForLocation(Genba.sharedInstance.gps.currentLocation))
//将图像调整为所需的
let resized = self.resizeNSDataImage(imageData,newSize:Genba.sharedInstance.imageSize)
//将新的exif附加到调整大小image
let attach = self.attachEXIFtoImage(resized,EXIF:newEXIF)
//将文件保存到相机胶卷和应用程序中
self.saveFile(附加)
} else {
debugPrint(self.n,#line,Error capture photo \(error.localizedDescri )
}
}
}
帮手函数在这里
//结合exif字典
func addGPSToEXIF(old:NSDictionary,new:NSDictionary) - > NSDictionary {
old.setValue(new,forKey:kCGImagePropertyGPSDictionary as String)
返回旧
}
//获取NSDictionary从图像
func getEXIFFromImage(image:NSData) - > NSDictionary {
let imageSourceRef = CGImageSourceCreateWithData(image,nil);
let currentProperties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef !, 0,nil)
let mutableDict = NSMutableDictionary(dictionary:currentProperties!)
return mutableDict
//将EXIF DIctionary数据附加到图像
func attachEXIFtoImage(image:NSData,EXIF:NSDictionary) - > NSData {
让imageDataProvider:CGDataProviderRef = CGDataProviderCreateWithCFData(image)!
让imageRef:CGImageRef = CGImageCreateWithJPEGDataProvider(imageDataProvider,nil,true,.RenderingIntentDefault)!
let newImageData:CFMutableDataRef = CFDataCreateMutable(nil,0)
let type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,image / jpgas CFString,kUTTypeImage)
let destination:CGImageDestinationRef = CGImageDestinationCreateWithData(newImageData,(type?.takeRetainedValue())!, 1,nil)!
CGImageDestinationAddImage(destination,imageRef,EXIF as CFDictionaryRef)
CGImageDestinationFinalize(目标)
返回newImageData作为NSData
}
//用EXIF $ b $保存应用程序中的文件func saveFile(image:NSData){
//将文件保存为
let dataPath = Genba.sharedInstance.userdata_save_folder
让fileExists = dataPath.checkResourceIsReachableAndReturnError(nil)
if fileExists {
let formatter = NSDateFormatter()
formatter.dateFormat =YM-dd_HH-mm-ss
let time = formatter.stringFromDate(NSDate())
let savefilepath = dataPath.URLByAppendingPathComponent(time +。jpg)
let result = image.writeToURL(savefilepath ,原子:false)
如果结果{
savePhotoToLibraryWithURL(savefilepath)
} else {
debugPrint(n,#行,保存失败)
}
//调整NSData的图像大小
func resizeNSDataImage(inputImage:NSData,newSize:CGSize) - > NSData {
var smallerImage:NSData? = nil
image image = UIImage(data:inputImage)
UIGraphicsBeginImageContext(newSize)
image!.drawInRect(CGRect(origin:CGPointZero, newImage = UIGephicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
smallImage = UIImageJPEGRepresentation
返回小图!
}
func savePhotoToLibraryWithURL(image:NSURL){
let photoLibrary = PHPhotoLibrary.sharedPhotoLibrary()
photoLibrary.performChanges({
PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(image)
}){(成功:Bool,错误:NSError?) - >如果成功{b
$ b} else {
print(self.n,#line,写入照片库时出错:\(error!.localizedDescription)),则无效
code $ pre
I'm trying to add GPS metadata to the image taken with AVFoundation
in swift. I have the code pasted below but it doesn't work yet. Where is my mistake?
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let imgDataProvider = CGDataProviderCreateWithCFData(imageData);
let imageRef = CGImageCreateWithJPEGDataProvider(imgDataProvider, nil, true, .RenderingIntentDefault)
let properties = self.getImageProperties(imageData)
let mutableDictionary: NSMutableDictionary = NSMutableDictionary(dictionary: properties)
mutableDictionary.setValue(self.getGPSDictionary(), forKey: kCGImagePropertyGPSDictionary as String)
let newImageData = CFDataCreateMutable(nil, 0)
let type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, "image/jpg" as CFString, kUTTypeImage)
let destination = CGImageDestinationCreateWithData(newImageData, (type?.takeRetainedValue())!, 1, nil)
CGImageDestinationAddImage(destination!, imageRef!, mutableDictionary)
CGImageDestinationFinalize(destination!)
let newImage = newImageData
getImageProperties method:
private func getImageProperties(data: NSData) -> NSDictionary {
let imageSourceRef = CGImageSourceCreateWithData(data, nil);
let properties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef!, 0, nil)
let props = properties
return props!
}
getGPSDictionary method:
private func getGPSDictionary() -> NSDictionary {
let dictionary = [kCGImagePropertyGPSLatitude as String :"54",kCGImagePropertyGPSLongitude as String :"23"]
return dictionary
}
Yes, i know that coordinates are hardcoded so far but important for now is to make it working, i will update location.
解决方案 This is how I did it. This worked on Swift 2.2 iOS 9.2
@IBAction func shutter(sender: AnyObject) {
let connection = imageOutput.connectionWithMediaType(AVMediaTypeVideo)
// set the orientation
if connection.supportsVideoOrientation {
connection.videoOrientation = currentVideoOrientation()
}
imageOutput.captureStillImageAsynchronouslyFromConnection(connection) {
(sampleBuffer: CMSampleBuffer!, error: NSError!) -> Void in
if sampleBuffer != nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
// get the old EXIF
let oldEXIF = self.getEXIFFromImage(imageData)
// add gps info to the old exif
let newEXIF = self.addGPSToEXIF(oldEXIF, new: self.getGPSDictionaryForLocation(Genba.sharedInstance.gps.currentLocation))
// resize the image to desired
let resized = self.resizeNSDataImage(imageData, newSize: Genba.sharedInstance.imageSize)
// attach the new exif to the resized image
let attached = self.attachEXIFtoImage(resized, EXIF: newEXIF)
// save the file to the camera roll and inside the app
self.saveFile(attached)
} else {
debugPrint(self.n,#line,"Error capturing photo \(error.localizedDescription)")
}
}
}
The helper functions are here
// combine exif dictionaries
func addGPSToEXIF(old:NSDictionary, new:NSDictionary) -> NSDictionary {
old.setValue(new, forKey: kCGImagePropertyGPSDictionary as String)
return old
}
// get an NSDictionary from an image
func getEXIFFromImage(image:NSData) -> NSDictionary {
let imageSourceRef = CGImageSourceCreateWithData(image, nil);
let currentProperties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef!, 0, nil)
let mutableDict = NSMutableDictionary(dictionary: currentProperties!)
return mutableDict
}
// Attach EXIF DIctionary data to an image
func attachEXIFtoImage(image:NSData, EXIF:NSDictionary) -> NSData {
let imageDataProvider:CGDataProviderRef = CGDataProviderCreateWithCFData(image)!
let imageRef:CGImageRef = CGImageCreateWithJPEGDataProvider(imageDataProvider, nil, true, .RenderingIntentDefault)!
let newImageData:CFMutableDataRef = CFDataCreateMutable(nil, 0)
let type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, "image/jpg" as CFString, kUTTypeImage)
let destination:CGImageDestinationRef = CGImageDestinationCreateWithData(newImageData, (type?.takeRetainedValue())!, 1, nil)!
CGImageDestinationAddImage(destination, imageRef, EXIF as CFDictionaryRef)
CGImageDestinationFinalize(destination)
return newImageData as NSData
}
// save file within app with EXIF
func saveFile(image: NSData) {
// Saves the file out
let dataPath = Genba.sharedInstance.userdata_save_folder
let fileExists = dataPath.checkResourceIsReachableAndReturnError(nil)
if fileExists {
let formatter = NSDateFormatter()
formatter.dateFormat = "Y-M-dd_HH-mm-ss"
let time = formatter.stringFromDate(NSDate())
let savefilepath = dataPath.URLByAppendingPathComponent(time+".jpg")
let result = image.writeToURL(savefilepath, atomically: false)
if result {
savePhotoToLibraryWithURL(savefilepath)
} else {
debugPrint(n,#line,"failed to save")
}
}
}
// resize image from NSData
func resizeNSDataImage (inputImage:NSData, newSize:CGSize) -> NSData {
var smallerImage:NSData? = nil
let image = UIImage(data: inputImage)
UIGraphicsBeginImageContext(newSize)
image!.drawInRect(CGRect(origin: CGPointZero, size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
smallerImage = UIImageJPEGRepresentation(newImage, 1)
return smallerImage!
}
func savePhotoToLibraryWithURL(image: NSURL) {
let photoLibrary = PHPhotoLibrary.sharedPhotoLibrary()
photoLibrary.performChanges({
PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(image)
}) { (success: Bool, error: NSError?) -> Void in
if success {
} else {
print(self.n,#line,"Error writing to photo library: \(error!.localizedDescription)")
}
}
}
这篇关于添加GPS元数据字典到AVFoundation拍摄的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!