views:

4404

answers:

13

It's well known that UIImagePickerController doesn't return the metadata of the photo after selection. However, a couple of apps in the app store (Mobile Fotos, PixelPipe) seem to be able to read the original files and the EXIF data stored within them, enabling the app to extract the geodata from the selected photo.

They seem to do this by reading the original file from the /private/var/mobile/Media/DCIM/100APPLE/ folder and running it through an EXIF library.

However, I can't work out a way of matching a photo returned from the UIImagePickerController to a file on disk. I've explored file sizes, but the original file is a JPEG, whilst the returned image is a raw UIImage, making it impossible to know the file size of the image that was selected.

I'm considering making a table of hashes and matching against the first x pixels of each image. This seems a bit over the top though, and probably quite slow.

Any suggestions?

A: 

You might be able to hash the image data returned by the UIImagePickerController and each of the images in the directory and compare them.

Frank Schmitt
That's an interesting idea - have you got any idea whether it works, and what the speed is like?
tomtaylor
No idea if it works, just an approach to try. If it works but performs poorly you might be able to cache the filenames and hashes in a plist so that you only have to calculate them once for existing images.
Frank Schmitt
A: 

Just a thought, but have you tried TTPhotoViewController in the Three20 project on GitHub?

That provides an image picker that can read from multiple sources. You may be able to use it as an alternative to UIImagePickerController, or the source might give you a clue how to work out how to get the info you need.

Simon
That would work, but you'd still have to read the images out of /private/var/mobile/Media/DCIM/100APPLE/ - all it does is provide a nicer UI on top of that.
tomtaylor
tomtaylor: don't expect Apple to approve an application that reads from that folder directly
rpetrich
A: 

Is there a specific reason you want to extract the location data from the image? An alternative could be to get the location separately using the CoreLocation framework. If it's only the geodata you need, this might save you some headaches.

RupertP
That's what the flickr app does and it's in fact very confusing: When uploading a picture you took on a trip from at home, it will show your current location rather than the place where the picture was taken...
FRotthowe
Yes, that's what I'm trying to avoid. I also want the DateTakenOriginal from the EXIF header.
tomtaylor
+1  A: 

This is something that the public API does not provide, but could be useful to many people. Your primary recourse is to file a bug with Apple that describes what you need (and it can be helpful to explain why you need it as well). Hopefully your request could make it into a future release.

After filing a bug, you could also use one of the Developer Technical Support (DTS) incidents that came with your iPhone Developer Program membership. If there is a public way to do this, an Apple engineer will know. Otherwise, it may at least help get your plight a bit more attention within the mothership. Best of luck!

natevw
Thanks - I've just filed a bug: #7388190.
tomtaylor
+7  A: 
yonel
Yes, that's what I originally tried. But thanks for your efforts - if you come across another way, it'd be great if you let us know here.
tomtaylor
I'm going to try to geotag the photo on my own using the exif iphone library, I'll keep you informed (seems "simple" from the user guide but not really straight forward... :/)
yonel
Thanks yonel, but I'm actually looking to fetch the EXIF information from photos taken by the Camera app.
tomtaylor
@tom : yes, I know I derived a bit from your original subject :)
yonel
Great answer. Deserves to be the accepted answer imo.
Felixyz
Doesn't really answer the original question!
Gerald Kaszuba
A: 

Yonel -

I'm working with the exif-iphone library as well, just found it. How can a user pick an image from their camera roll that I can then parse with the iphone-exif tactics? That's what I'm (and it looks like most of us are) missing.

Have you had any luck?

quigs
As it stands, you can't do this. UIImagePickerController does not return this information in the selected image.
tomtaylor
No, as said in my post / solution, this is not possible, the UIImage representation does not encapsulate the EXIF representation. It's up to you to convert the UIImage into JPeg and then tag it with your exif info.
yonel
+1  A: 

I spend a while working on this as well for an application I was contracted to build. Basically as the API currently stands it is not possible. The basic problem is the UIImage class STRIPS all EXIF data except for the orientation out. Also the function to save to the camera roll strips this data out. So basically the only way to grab and maintain any extra EXIF data is to save it in a private "camera roll" in your application. I have filed this bug with apple as well and emphasized the need to the app reviewer reps we've been in contact with. Hopefully someday they'll add it in.. Otherwise it makes having GEO tagging completely useless as it only works in the "stock" camera application.

NOTE Some applications on the app store hack around this. By, what I have found, directly accessing the camera roll and SAVING photos straight to it to save GEO data. However this only works with the camera roll/saved photos and NOT the rest of the photo library. The photos "synced" to your phone from your computer have all EXIF data except for orientation stripped.

I still can't understand why those applications were approved (heck they even DELETE from the camera roll) and our application which does none of that is still being held back.

Urkle
+1  A: 

The naughty way to do this is to traverse the UIImagePickerViewController's views and pick out the selected image in the delegate callback.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

  id thumbnailView = [[[[[[[[[[picker.view subviews] 
                  objectAtIndex:0] subviews]
                  objectAtIndex:0] subviews]
                objectAtIndex:0] subviews]
                objectAtIndex:0] subviews]
              objectAtIndex:0];

  NSString *fullSizePath = [[[thumbnailView selectedPhoto] fileGroup] pathForFullSizeImage];
  NSString *thumbnailPath = [[[thumbnailView selectedPhoto] fileGroup] pathForThumbnailFile];

  NSLog(@"%@ and %@", fullSizePath, thumbnailPath);

}

That will give you the path to the full size image, which you can then open with an EXIF library of your choice.

But, this calls a Private API and these method names will be detected by Apple if you submit this app. So don't do this, OK?

tomtaylor
A: 

An upgrade to my app that reads directly from /private/var/mobile/Media/DCIM/100APPLE/ got rejected by Apple, even though previous versions were allowed. I hope this means Apple is going to add EXIF capabilities to the API, but for now the only way to have exif is to add it yourself to photos taken via your own app's camera functions. Images taken earlier with the built-in camera app will be devoid of valuable exif info.

Adriaan
+1  A: 

Use the UIImagePickerControllerMediaURL dictionary key to get the file URL to the original file. Despite what the documentation says, you can get the file URL for photos and not only movies.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    // Try to get the original file.
    NSURL *originalFile = [info objectForKey:UIImagePickerControllerMediaURL];
    if (originalFile) {
        NSData *fileData = [NSData dataWithContentsOfURL:originalFile];
    }
}
lucius
A: 

it seems that photo attained by UIImagePickerControllerMediaURL don't have exif tags at all

GameBit
+3  A: 

Apple has added an Image I/O Framework in iOS4 which can be used to read EXIF data from pictures. I don't know if the UIImagePickerController returns a picture with the EXIF data embedded though.

Edit: In iOS4 you can fetch the EXIF data by grabbing the value of the UIImagePickerControllerMediaMetadata key in the info dictionary which is passed to the UIImagePickerControllerDelegate delegate.

Yannick Compernol
A: 

Tested on iphone 3.1.2 or early,

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    // Try to get the original file.
    NSURL *originalFile = [info objectForKey:UIImagePickerControllerMediaURL];
    if (originalFile) {
        NSData *fileData = [NSData dataWithContentsOfURL:originalFile];
    }
}

originalFile is always is nil for photo, since these is not UIImagePickerControllerMediaURL key for photo at (NSDictionary *)info.

any one have solution to get photo's URL at didFinishPickingMediaWithInfo to get exif tag for any photo???

bygreencn