iOS Swift. How to Get a Gps Metadata from Just a Uiimage (Nsurl)

iOS Swift. How to get a GPS metadata from just a UIImage (NSURL)?

Answering my own question. The memory-effective and fast way to get a GPS metadata is

let options = [kCGImageSourceShouldCache as String: kCFBooleanFalse]
if let data = NSData(contentsOfURL: url), imgSrc = CGImageSourceCreateWithData(data, options) {
let metadata = CGImageSourceCopyPropertiesAtIndex(imgSrc, 0, options) as Dictionary
let gpsData = metadata[kCGImagePropertyGPSDictionary] as? [String : AnyObject]
}

The second option is

if let img = CIImage(contentsOfURL: url), metadata = img.properties(), 
gpsData = metadata[kCGImagePropertyGPSDictionary] as? [String : AnyObject] { … }

it looks nicer in Swift but uses more memory (tested via Profiler).

Extract GPS data from photo

I found a solution using the following code:

 if picker.sourceType == UIImagePickerControllerSourceType.PhotoLibrary
{
if let currentLat = pickedLat as CLLocationDegrees?
{
self.latitude = pickedLat!
self.longitude = pickedLong!
}
else
{
var library = ALAssetsLibrary()
library.enumerateGroupsWithTypes(ALAssetsGroupAll, usingBlock: { (group, stop) -> Void in
if (group != nil) {

println("Group is not nil")
println(group.valueForProperty(ALAssetsGroupPropertyName))
group.enumerateAssetsUsingBlock { (asset, index, stop) in
if asset != nil
{
if let location: CLLocation = asset.valueForProperty(ALAssetPropertyLocation) as CLLocation!
{ let lat = location.coordinate.latitude
let long = location.coordinate.longitude

self.latitude = lat
self.longitude = lat

println(lat)
println(long)
}
}
}
} else
{
println("The group is empty!")
}
})
{ (error) -> Void in
println("problem loading albums: \(error)")
}
}
}

What it does is that it reads the entire album and prints the location if the photo has that property, else it prints "location not found". It does so for every photo in the album.So I have another question... I want to display the location info just for the photo that I have selected, not for the entire album. Does anyone have a clue how this can be accomplished?

Write UIImage along with metadata (EXIF, GPS, TIFF) in iPhone's Photo library

The function: UIImageWriteToSavePhotosAlbum only writes the image data.

You need to read up on the ALAssetsLibrary

The method you ultimately want to call is:

 ALAssetsLibrary *library = [[ALAssetsLibrary alloc]
[library writeImageToSavedPhotosAlbum:metadata:completionBlock];

How obtain GPS data from a photo

I hope this will help you:-

//step1:- import Photos

//step2:- when you presenting imagepicker controller

if PHPhotoLibrary.authorizationStatus() == .authorized || PHPhotoLibrary.authorizationStatus() == .authorized{
PHPhotoLibrary.requestAuthorization { [weak self](_) in
// Present the UIImagePickerController
self?.present(self!.imagePicker, animated: true, completion: nil)
}
}

swift3.0 and Swift4.0

//step3:-
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

//obtaining saving path
let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let imagePath = documentsPath?.appendingPathComponent("image.jpg")
// extract image from the picker and save it
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
let data = UIImageJPEGRepresentation(pickedImage, 0.75)
data.write(toFile: localPath!, atomically: true)
}

let coordinate = (info[UIImagePickerControllerPHAsset] as? PHAsset)?.location?.coordinate
print(coordinate?.latitude ?? "No latitude found")
print(coordinate?.longitude ?? "No longitude found")
self.dismiss(animated: true, completion: nil)
}

swift 4.2

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

//obtaining saving path
let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
let imagePath = documentsPath?.appendingPathComponent("image.jpg")

// extract image from the picker and save it
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {

let imageData = pickedImage.jpegData(compressionQuality: 0.75)
try! imageData?.write(to: imagePath!)
}

let coordinate = (info[UIImagePickerController.InfoKey.phAsset] as? PHAsset)?.location?.coordinate
print(coordinate?.latitude ?? "No latitude found")
print(coordinate?.longitude ?? "No longitude found")
self.dismiss(animated: true, completion: nil)
}

Sample Image

Thanks

How to write exif metadata to an image (not the camera roll, just a UIImage or JPEG)

UIImage does not contain metadata information (it is stripped). So if you want to save it without using the imagepicker method (not in camera roll):

Follow the answer here to write to a file with the metadata intact:

Problem setting exif data for an image

no idea why would this be downvoted but here is the method:

In this case im getting the image through AVFoundation and this is what goes in the

[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection 
completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
// code here
}

block code:

    CFDictionaryRef metaDict = CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate);

CFMutableDictionaryRef mutable = CFDictionaryCreateMutableCopy(NULL, 0, metaDict);

// Create formatted date
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:timeZone];
[formatter setDateFormat:@"HH:mm:ss.SS"];

// Create GPS Dictionary
NSDictionary *gpsDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:fabs(loc.coordinate.latitude)], kCGImagePropertyGPSLatitude
, ((loc.coordinate.latitude >= 0) ? @"N" : @"S"), kCGImagePropertyGPSLatitudeRef
, [NSNumber numberWithFloat:fabs(loc.coordinate.longitude)], kCGImagePropertyGPSLongitude
, ((loc.coordinate.longitude >= 0) ? @"E" : @"W"), kCGImagePropertyGPSLongitudeRef
, [formatter stringFromDate:[loc timestamp]], kCGImagePropertyGPSTimeStamp
, [NSNumber numberWithFloat:fabs(loc.altitude)], kCGImagePropertyGPSAltitude
, nil];

// The gps info goes into the gps metadata part

CFDictionarySetValue(mutable, kCGImagePropertyGPSDictionary, (__bridge void *)gpsDict);

// Here just as an example im adding the attitude matrix in the exif comment metadata

CMRotationMatrix m = att.rotationMatrix;
GLKMatrix4 attMat = GLKMatrix4Make(m.m11, m.m12, m.m13, 0, m.m21, m.m22, m.m23, 0, m.m31, m.m32, m.m33, 0, 0, 0, 0, 1);

NSMutableDictionary *EXIFDictionary = (__bridge NSMutableDictionary*)CFDictionaryGetValue(mutable, kCGImagePropertyExifDictionary);

[EXIFDictionary setValue:NSStringFromGLKMatrix4(attMat) forKey:(NSString *)kCGImagePropertyExifUserComment];

CFDictionarySetValue(mutable, kCGImagePropertyExifDictionary, (__bridge void *)EXIFDictionary);

NSData *jpeg = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer] ;

After this code you will have your image in the jpeg nsdata and the correspoding dictionary for that image in the mutable cfdictionary.

All you have to do now is:

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)jpeg, NULL);

CFStringRef UTI = CGImageSourceGetType(source); //this is the type of image (e.g., public.jpeg)

NSMutableData *dest_data = [NSMutableData data];

CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data,UTI,1,NULL);

if(!destination) {
NSLog(@"***Could not create image destination ***");
}

//add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) mutable);

//tell the destination to write the image data and metadata into our data object.
//It will return false if something goes wrong
BOOL success = CGImageDestinationFinalize(destination);

if(!success) {
NSLog(@"***Could not create data from image destination ***");
}

//now we have the data ready to go, so do whatever you want with it
//here we just write it to disk at the same path we were passed

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"ImagesFolder"];

NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder

// NSString *imageName = @"ImageName";

NSString *fullPath = [dataPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpg", name]]; //add our image to the path

[dest_data writeToFile:fullPath atomically:YES];

//cleanup

CFRelease(destination);
CFRelease(source);

Note how I'm not saving using the ALAssets but directly into a folder of my choice.

Btw most of this code can be found in the link I posted at first.

extract GPS data from photo iOS swift

I found the solution,the code is correct! but when I copy a photo to the simulator via drag and drop the GPS data is removed from the photo for some reason, I store photos onto Dropbox and download them through safari of the simulator!
by reference to Is it possible to access a photo's geotag metadata from within the simulator?

imagePickerController with GPS data (Swift)

Try this:

Remember to import AssetsLibrary

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
picker.dismissViewControllerAnimated(true, completion: { () in
if (picker.sourceType == .PhotoLibrary) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let library = ALAssetsLibrary()
var url: NSURL = info[UIImagePickerControllerReferenceURL] as! NSURL

library.assetForURL(url, resultBlock: { (asset: ALAsset!) in
if asset.valueForProperty(ALAssetPropertyLocation) != nil {
let latitude = (asset.valueForProperty(ALAssetPropertyLocation) as! CLLocation!).coordinate.latitude
let longitude = (asset.valueForProperty(ALAssetPropertyLocation) as! CLLocation!).coordinate.longitude
println("\(latitude), \(longitude)")
}
},
failureBlock: { (error: NSError!) in
println(error.localizedDescription)
})
}
})
}

How to get image metadata in ios

CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef) aUrl, NULL);
CGImageSourceRef source = CGImageSourceCreateWithData( (CFDataRef) theData, NULL);
NSDictionary* metadata = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source,0,NULL));
CFRelease(source);

Check the dictionary contents here.



Related Topics



Leave a reply



Submit