Error getting EXIF information in Swift 3/4 - image-processing

I want to get EXIF data from images in my PhotoLibrary but cannot find the correct method. I have used answers from this question, and this one. I'm getting the following console output:
imageSource: <UIImage: 0x6080000b8a20> size {3000, 2002} orientation 0 scale 1.000000
2017-09-18 11:24:28.513567+0300 PhotoTest[10581:6526935] CGImageSourceCopyPropertiesAtIndex:3517: *** ERROR: CGImageSourceCopyPropertiesAtIndex: source is not a CGImageSourceRef
2017-09-18 11:24:29.071412+0300 PhotoTest[10581:6527417] [discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}
This is my current code attempt. I'd appreciate any solutions or ideas. I've been scratching my head trying to divine various methods, but I don't know enough about imageIO to solve the problem.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
self.dismiss(animated: true, completion: nil)
let bigImage = info[UIImagePickerControllerOriginalImage] as? UIImage
photoImageView.image = bigImage
imageData = UIImagePNGRepresentation(bigImage!) as NSData?
if let imageSource = info[UIImagePickerControllerOriginalImage] {
print("imageSource: ", imageSource)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource as! CGImageSource, 0, nil)
//print("imageProperties: ", imageProperties!)
if let dict = imageProperties as? [String: Any] {
print(dict)
}
}
dismiss(animated: true, completion: nil)
}

You're seeing the:
*** ERROR: CGImageSourceCopyPropertiesAtIndex: source is not a CGImageSourceRef
line because you need to create your imageSource via one of the CGImageSourceCreate... API's.
Try doing this:
if let bigImage = info[UIImagePickerControllerOriginalImage] as? UIImage
{
if let imageData = UIImagePNGRepresentation(bigImage)
{
if let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil)
{
print("imageSource: ", imageSource)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)
//print("imageProperties: ", imageProperties!)
if let dict = imageProperties as? [String: Any] {
print(dict)
}
}
}
}

I found a different solution, as follows:
import Photos
import PhotosUI
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let assetURL = info[UIImagePickerControllerReferenceURL] 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 imageProperties2 = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
print("imageProperties2: ", imageProperties2)
}
})
dismiss(animated: true, completion: nil)
}
Hope this helps others.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let exifData = info[.mediaMetadata] as? [String: Any] {
//print(exifData)
}
}

Related

How to crop image in freestyle(as user wants) while selecting from image picker in ios

can any one help me in cropping image in freestyle as user wants.
I tried the below method, but its cropping image only in square shape.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage{
pickImage.image = image
let imageData:NSData = UIImageJPEGRepresentation(pickImage.image!, 0.5) as! NSData
if(imageData != nil){
// let imageStr1 = imageData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let imageStr1 = imageData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters)
imageStr = "data:image/png;base64,\(imageStr1))"
}
}
dismiss(animated: true, completion: nil)
}
Please try to answer me with apple default methods, if available.
Thanks in advance.

Swift 4.2 Cannot convert value of type '(UIImagePickerController.InfoKey).Type' to expected argument type 'UIImagePickerController.InfoKey'

My below code was working just fine with swift 4 but after upgrading to swift 4.2 I am getting this error, I had wasted my 3 hours searching what's the issue but failed. Please if anyone can guide me how to fix this.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if postType == 2 {
let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey)] as! UIImage
mediaType.image = image
} else {
videoURL = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.mediaURL)] as? URL
do {
let asset = AVURLAsset(url: videoURL!, options: nil)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImage(at: CMTime.init(value: 0, timescale: 1), actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
self.mediaType.image = thumbnail
} catch {
print("*** Error generating thumbnail: \(error)")
}
}
picker.dismiss(animated: true, completion: nil)
}
You can write like...
if let image = info[.originalImage] as? UIImage {
print("image found")
//do something with an image
} else {
print("Not able to get an image")
}
EDIT:
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//for original image
let originalImage = info[.originalImage]
//for edited image
let editedImage = info[.editedImage]
if #available(iOS 11.0, *) {
//gives URL of image picked by user
let imageURL = info[.imageURL]
}
//gives URL of media picked by user
let mediaURL = info[.mediaURL]
}
info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey)]
does not make any sense. You are specifying the whole enum type InfoKey instead of a specific value, e.g.:
info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)]
Which can be probably also written just as:
info[.originalImage] as! UIImage
You can access the properties as follows.
var editedImage = (info[UIImagePickerControllerEditedImage] as? UIImage)!
var originalImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
{
// Local variable inserted by Swift 4.2 migrator.
let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)
if picker.sourceType == .photoLibrary || picker.sourceType == .camera
{
let img: UIImage = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.editedImage)] as! UIImage
EditedImage=img
WAProfile_UserImageView.image=EditedImage
picker.dismiss(animated: true, completion: nil)
}
}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKeyDictionary(_ input: [UIImagePickerController.InfoKey: Any]) -> [String: Any] {
return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)})}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKey(_ input: UIImagePickerController.InfoKey) -> String {
return input.rawValue}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion: nil)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
yourImgView.image = image
}
Although an old thread, the migrator added this function which seemed to fix things nicely:
// Function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKeyDictionary(_ input:
[UIImagePickerController.InfoKey: Any]) -> [String: Any] {
return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)})
}

Getting video url from image picker in iOS

I'm facing a problem selecting the video url from the photo gallery. When the image picker is presented, it can not choose but I try to choose it. It automatically compressing and image picker is not dissmissed.
This is my code.
self.imagePickerController.sourceType = .savedPhotosAlbum
self.imagePickerController.delegate = self
self.imagePickerController.mediaTypes = [kUTTypeMovie as! String]
self.present(self.imagePickerController, animated: true, completion: nil)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
var videoURL: NSURL? = nil
videoURL = info["UIImagePickerControllerReferenceURL"] as? NSURL
print(videoURL)
imagePickerController.dismiss(animated: true, completion: nil)
}
In Swift 4.2, you must use a new enum provided by Apple to capture the video URL:
// Using the full key
if let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
// Do something with the URL
}
// Using just the information key value
if let url = info[.mediaURL] as? URL {
// Do something with the URL
}
You can read about mediaURL here.
Specifies the filesystem URL for the movie.
You can get video url from info like,
videoURL = info[UIImagePickerControllerMediaURL] as? URL
print("videoURL:\(String(describing: videoURL))")
self.dismiss(animated: true, completion: nil)
In Swift 4.2:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let mediaURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL else { return }
// You can do whatever youo want here....
}
Just simple like this.
extension HomeVC: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let videoUrl = info[UIImagePickerControllerMediaURL] as! URL
// Do something with the videoUrl
DispatchQueue.main.async { // Dismiss it, remember using `picker`
picker.dismiss(animated: true, completion: nil)
}
}
}
Use below code for Select the video without compression :
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any]) {
let mediaType = info[UIImagePickerControllerMediaType] as? String
let videoString = kUTTypeVideo as? String
let movieString = kUTTypeMovie as? String
if (mediaType == videoString) || (mediaType == movieString) {
var videoRef = info[UIImagePickerControllerReferenceURL] as? URL
var refResult = PHAsset.fetchAssets(withALAssetURLs: [videoRef], options: nil) as? PHFetchResult
var videoRequestOptions = PHVideoRequestOptions()
videoRequestOptions.version() = .original
PHImageManager.default().requestAVAsset(forVideo: refResult.firstObject as? PHAsset ?? PHAsset(), options: videoRequestOptions, resultHandler: {(_ asset: AVAsset, _ audioMix: AVAudioMix, _ info: [AnyHashable: Any]) -> Void in
if (asset is AVURLAsset) {
var originURL: URL? = (asset as? AVURLAsset)?.url
// Now you have the URL of the original video.
picker.dismiss(animated: true, completion: nil)
}
else
{
picker.dismiss(animated: true, completion: nil)
}
})
}
}

iOS Swift Cannot acces EXIF data on stored photo

I need to get location of the pics in the device photo gallery. To do so I am trying to load the Exif data of the image.
This is my code:
import ImageIO
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
let ciImage = CIImage(image: image!)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(ciImage as! CGImageSource, 0, nil) as Dictionary?
if let dict = imageProperties as? [String: Any] {
print(dict)
}
}
When I try to run my code on the device, the App crash.
I think the problem is in the cast, I tried to do some manipulaiton, but I am not able to convert my UIImage in CFImageSource type.
You can't cast a CIImage (nor a UIImage) to a CGImageSource. To create a CGImageSource do:
guard let imageData = UIImageJPEGRepresentation(uiImage, 1)
else { fatalError("Error getting image data") }
guard let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil)
else { fatalError("Error creating image source") }
let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)
UIImageJPEGRepresentation returns the image as a JPEG image so it doesn't matter what format uiImage originally is in.

How to get the name of file for reference url using Photos framework?

This is how I get an NSURL:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? NSURL {
//access the file name
}
}
It was using ALAssetsLibrary:
let assetsLibrary = ALAssetsLibrary()
assetsLibrary.assetForURL(referenceUrl, resultBlock: { asset in
let filename = asset.defaultRepresentation().filename()
}, failureBlock: nil)
but since iOS 9 it is deprecated.
The simplest answer:
if let asset = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl], options: nil).firstObject as? PHAsset {
PHImageManager.defaultManager().requestImageDataForAsset(asset, options: nil, resultHandler: { _, _, _, info in
if let fileName = (info?["PHImageFileURLKey"] as? NSURL)?.lastPathComponent {
//do sth with file name
}
})
}

Resources