swift UIImagePickerController and extracting EXIF data from existing photos - swift

I need to get location data (coordinates for latitude and longitude) from an image picked from PhotoLibrary using UIImagePickerController. Existing answers proposes using fetchAssetsWithALAssetURLs, but it is deprecated for iOS 8 to 11, so I wonder what's the alternative?
Thanks!

This worked for me. For new iOS versions, use the following lines of code.
var asset: PHAsset?
asset = info[UIImagePickerControllerPHAsset] as? PHAsset
Note that asset = nil if the user did not give permission to access his Photo Library since the PHAsset data is sensitive.
To obtain permission, edit Info.plist accordingly and request for permission using PHPhotoLibrary.requestAuthorization().

If you are only supporting iOS 11 and later then you can directly get the PHAsset using the .phAsset key. You only need to use PHAsset fetchAssetsWithALAssetURLs if you need to support iOS 10 or earlier.
Once you have the PHAsset reference, then you can access the location property to get the coordinates of the image.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var asset: PHAsset?
if #available(iOS 11.0, *) {
asset = info[.phAsset] as? PHAsset
} else {
if let url = info[.referenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [url], options: nil)
asset = result.firstObject
}
}
if let asset = asset {
if let location = asset.location {
print("Image location is \(location.coordinate.latitude), \(location.coordinate.longitude)")
}
}
}

Related

Get Filename From PHAsset swift 5 IOS13

My Question is how we get file Name From PHAsset Which Are Picked By gallery
var allSmallPic: [PHAsset] = []
PHImageManager.default().requestImage(for: allSmallPic[indexPath.row], targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: nil) { (image, info) in
cell.ImageVieww.image = image
cell.Labell.text = "\(String(describing: info!))"
print(info!)
}
let resource1 = PHAssetResource.assetResources(for:self.allSmallPic[indexPath.row])
print("Get resources\(resource1)")
cell.Labell.text = resource1[0].originalFilename
As you Know PHAsset is representation of an image, video, or Live Photo in the Photos library.
So I want to show the file names into my tableViewCell Like this
when no results found i'm start read documentations and i found PHAssetResource and they help me to Get image name
let resource1 = PHAssetResource.assetResources(for:self.allSmallPic[indexPath.row])
print("Get resources\(resource1)")
cell.Labell.text = resource1[0].originalFilename
The allSmallPic is global array which store PHAsset

How to grab all metadata from any image?

I have been searching google and could not find a solution for my problem. I have some code that grabs metadata from images the user picks from the image picker. The problem is that my code doesn't grab ALL metadata from HEIC and RAW images. I set up some print statements to find out which data my code doesn't grab from HEIC.
Manufacturer not found
Camera model not found
Camera software not found
Aperture not found
Focal length not found
ISO not found
Shutter speed not found
//And this is my metadata extracting code block
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[.originalImage] as? UIImage
let url = info[.imageURL]
let optionalImageData = try? Data(contentsOf: url as! URL)
guard let imageData = optionalImageData else { return }
let source: CGImageSource = CGImageSourceCreateWithData(imageData as CFData, nil)!
let metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [AnyHashable: Any]
print(metadata!)
self.dismiss(animated: true, completion: nil)
}
I'm going to guess that you have not obtained user permission to access the photos library. You are allowed to present the picker even so, but the information that you can receive in response is very limited. If you have user permission, you can receive the image as a PHAsset and you can get the desired metadata from the photos library.

File Directory Changing Every Reboot Swift iOS

I am currently saving images a user selects from their photo library & saving the url to User Defaults.
The issue I am currently facing is whenever my app reboots, such as an Xcode re-launch the URL I am saving to User Defaults is no longer valid. From my understanding/researching I need to save a relative URL for the image; however I am not having any luck doing this correctly. This occurs with both simulator & actual device.
From my UIImagePicker here are my steps:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.originalImage] as? UIImage else { return }
let savingImage : SavingImage = SavingImage()
let ourStringedUrl : String = savingImage.saveImageDocumentDirectory(image: image, imageName: image.description)
}
From SavingImage, here is the saving of the photo itself
func getDirectoryPath() -> NSURL {
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("AllImages")
let url = NSURL(string: path)
return url!
}
func saveImageDocumentDirectory(image: UIImage, imageName: String) -> String {
let fileManager = FileManager.default
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("AllImages")
if !fileManager.fileExists(atPath: path) {
try! fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
}
let url = NSURL(string: path)
let imagePath = url!.appendingPathComponent(imageName)
let urlString: String = imagePath!.absoluteString
let imageData = image.jpegData(compressionQuality: 1)
fileManager.createFile(atPath: urlString as String, contents: imageData, attributes: nil)
return urlString as String
}
& Finally here is how I am loading the image itself:
func getImageFromDocumentDirectory(imageName : String) -> UIImage {
let fileManager = FileManager.default
var ourImage : UIImage!
let imagePath = "\(imageName)"
let urlString: String = imagePath
if fileManager.fileExists(atPath: urlString) {
ourImage = UIImage(contentsOfFile: urlString)
} else {
if ourImage == nil {
ourImage = UIImage(named: "defaultImage.png")
}
}
return ourImage
}
Where am I going wrong with the loading aspect? How exactly should I be saving the URL?
The URL that is being saved looks something similar to the following:
//var/mobile/Containers/Data/Application/17C16D0D-1BFA-44F5-A6BD-18DFAEA051E0/Documents/AllImages/%3CUIImage:0x280a393b0%20anonymous%20%7B3024,%204032%7D%3E
But will come up as nil upon loading the image on reboot.
The new directory will be created every time you reboot your simulator or every time you install new build to device. (Uninstall previous and install new). iOS does not give us permission to select the directory. As you install new application it will create its sandbox. Please make sure you check your directory on the same build.
An alternative might be to use iCloud Drive and upload your image there. The iCloud drive is linked to an user's iCloud account, and therefore should persist in case of an app update.
Here's a great tutorial to get started: https://theswiftdev.com/2018/05/17/how-to-use-icloud-drive-documents/
Here's a link to the docs: https://developer.apple.com/icloud/icloud-drive/

using a local image from the device in order to classify it successfully

I am writing a visual recognition application that uses VisualRecognition.classify in order to classify images. I have configured my Swift environment and haven't been able to classify images when including a URL from the internet:
I have now created an application that uses the camera and photo library to allow users to take photos and have them classified. I am running into issues when passing along an fileURL from the device to the VisualRecognition service though.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
imageView.image = image
imagePicker.dismiss(animated: true, completion: nil)
let visualRecongnition = VisualRecognition(version: version, apiKey: apiKey)
let imageData = image.jpegData(compressionQuality: 0.01)
let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentURL.appendingPathComponent("tempImage.jpg")
try? imageData?.write(to: fileURL, options: [])
visualRecongnition.classify(imageFile: fileURL, success: { (classifiedImages) in
print(classifiedImages)
}) // getting error here " Missing argument for parameter 'completionHandler' in call"
}else {
print("There was an error picking Image")
}
}
I have even attempted to include the NSURL directly into the classify call as I have done with the working external URL, but still run into the same error. Would really like to see how to use a local image from the device in order to classify it successfully
The problem is that your call to classify does not correspond to the signature of the classify method. In this line:
visualRecongnition.classify(imageFile: fileURL, success: { (classifiedImages) in
change success to completionHandler, and add a second parameter in the closure (even if you ignore it), like this:
visualRecongnition.classify(imageFile: fileURL, completionHandler: { classifiedImages,_ in
You must first request permission to use the camera and library. Open your Info.plist file in Source code mode, and add the following lines:
<key>NSCameraUsageDescription</key>
<string>Ask for permission to use camera.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Ask for permission to use Photo Library</string>
If you also want to be able to write images to the Camera Roll add this too:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Ask for permission to save images to Photo library</string>

Swift 3 and Xcode 8 : Get Image From URL Path Stored in SQLITE Database Field

I have Implemented the Following code to add the image into Document directory and store the Path in my sqlite Database
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePath = imagesDirectoryPath + "/\(Date().description.replacingOccurrences(of: " ", with: "")).png"
print(imagePath)
let data = UIImagePNGRepresentation(image)
print(data!)
let success = FileManager.default.createFile(atPath: imagePath, contents: data, attributes: nil)
print(success)
dismiss(animated: true) { () -> Void in
}
}
Can Anyone help me how to get image back into My Tableview Using this Path as shown in the Image.
In the Table View cellForRowAt Method Or In Ur case if u want to display image in some other Case
You can Simply Do this by
let imageURL = URL(fileURLWithPath: student.Image_URL)
cell.imgProfileDisplay.image = UIImage(contentsOfFile: imageURL.path)
This will convert the image from the URL that we store in our DataBAse.
For Full Source Code of the Implementation kindly Comment.
Thanks