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
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.
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)})
}
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)
}
})
}
}
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.
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
}
})
}