Reading the GPS data from the image returned by the camera in iOS iphone

38,824

Solution 1

One possibility is to leaving CoreLocation running when the camera is visible. Record each CCLocation into an array along with the time of the sample. When the photo comes back, find its time, then match the closest CClocation from the array.

Sounds kludgy but it will work.

Solution 2

The problem is that since iOS 4 UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; strips the geolocation out. To solve this problem you have to use the original photo path to get access to the full image metadata. With something like this:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSURL *referenceURL = [info objectForKey:UIImagePickerControllerReferenceURL];
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
        ALAssetRepresentation *rep = [asset defaultRepresentation];
        NSDictionary *metadata = rep.metadata;
        NSLog(@"%@", metadata);

        CGImageRef iref = [rep fullScreenImage] ;

        if (iref) {
            self.imageView.image = [UIImage imageWithCGImage:iref];
        }
    } failureBlock:^(NSError *error) {
        // error handling
    }];

The output should be something like:

{
    ColorModel = RGB;
    DPIHeight = 72;
    DPIWidth = 72;
    Depth = 8;
    Orientation = 6;
    PixelHeight = 1936;
    PixelWidth = 2592;
    "{Exif}" =     {
        ApertureValue = "2.970854";
        BrightnessValue = "1.115874";
        ColorSpace = 1;
        ComponentsConfiguration =         (
            0,
            0,
            0,
            1
        );
        DateTimeDigitized = "2012:07:14 21:55:05";
        DateTimeOriginal = "2012:07:14 21:55:05";
        ExifVersion =         (
            2,
            2,
            1
        );
        ExposureMode = 0;
        ExposureProgram = 2;
        ExposureTime = "0.06666667";
        FNumber = "2.8";
        Flash = 24;
        FlashPixVersion =         (
            1,
            0
        );
        FocalLength = "3.85";
        ISOSpeedRatings =         (
            200
        );
        MeteringMode = 5;
        PixelXDimension = 2592;
        PixelYDimension = 1936;
        SceneCaptureType = 0;
        SensingMethod = 2;
        Sharpness = 2;
        ShutterSpeedValue = "3.9112";
        SubjectArea =         (
            1295,
            967,
            699,
            696
        );
        WhiteBalance = 0;
    };
    "{GPS}" =     {
        Altitude = "1167.528";
        AltitudeRef = 0;
        ImgDirection = "278.8303";
        ImgDirectionRef = T;
        Latitude = "15.8235";
        LatitudeRef = S;
        Longitude = "47.99416666666666";
        LongitudeRef = W;
        TimeStamp = "00:55:04.59";
    };
    "{TIFF}" =     {
        DateTime = "2012:07:14 21:55:05";
        Make = Apple;
        Model = "iPhone 4";
        Orientation = 6;
        ResolutionUnit = 2;
        Software = "5.1.1";
        XResolution = 72;
        YResolution = 72;
        "_YCbCrPositioning" = 1;
    };
}

Solution 3

We have worked a lot with the camera and UIImagePickerController and, at least up to and including iOS 5.1.1, it does not return location data in the metadata for either photos or videos shot with UIImagePickerController.

It doesn't matter whether location services is enabled for the Camera app or not; this controls the Camera app's use of location services, not the camera function within UIImagePickerController.

Your app will need to use the CLLocation class to get the location and then add it to the image or video returned from the camera. Whether your app can get the location will depend on whether the user authorizes access to location services for your app. And note that the user can disable location services for you app (or entirely for the device) at any time via Settings > Location Services.

Solution 4

You're not using the image data from the camera in the code you've posted, you've generated a JPEG representation of it, which would essentially discard all the metadata. Use image.CGImage like Caleb suggested.

Also:

This is also for a commercial product so I cannot use http://code.google.com/p/iphone-exif/.

The author quite clearly states that commercial licensing is available.

Solution 5

Can't say I've needed to do exactly this in my own stuff, but from the docs it seems pretty clear that if you're using UIImagePickerController you can get the image that the user just took from the -imagePicker:didFinishPickingMediaWithInfo: delegate method. Use the key UIImagePickerControllerOriginalImage to get the image.

Once you've got the image, you should be able to access its properties, including EXIF data, as described in QA1654 Accessing image properties with ImageIO. To create the CGImageSource, I'd look at CGImageSourceCreateWithData() and use the data that you get from the UIImage's CGImage method. Once you've got the image source, you can access the various attributes via CGImageSourceCopyProperties().

Share:
38,824
Paul Cezanne
Author by

Paul Cezanne

oblique @ alum dot mit dot edu SOreadytohelp

Updated on November 01, 2020

Comments

  • Paul Cezanne
    Paul Cezanne over 3 years

    I need to get the GPS coordinates of an image taken with the iOS device's camera. I do not care about the Camera Roll images, just the image taken with UIImagePickerControllerSourceTypeCamera.

    I've read many stackoverflow answers, like Get Exif data from UIImage - UIImagePickerController, which either assumes you are using the AssetsLibrary framework, which doesn't seem to work on camera images, or use CoreLocaiton to get the latitude/longitude from the app itself, not from the image.

    Using CoreLocation is not an option. That will not give me the coordinates when the shutter button was pressed. (With the CoreLocation based solutions, you either need to record the coords before you bring up the camera view or after, and of course if the device is moving the coordinates will be wrong. This method should work with a stationary device.)

    I am iOS5 only, so I don't need to support older devices. This is also for a commercial product so I cannot use http://code.google.com/p/iphone-exif/.

    So, what are my options for reading the GPS data from the image returned by the camera in iOS5? All I can think of right now is to save the image to Camera Roll and then use the AssetsLibrary, but that seems hokey.

    Thanks!


    Here's the code I wrote based on Caleb's answer.

        UIImage *image =  [info objectForKey:UIImagePickerControllerOriginalImage];
    
        NSData *jpeg = UIImageJPEGRepresentation(image,1.0);
        CGImageSourceRef  source ;
        source = CGImageSourceCreateWithData((__bridge CFDataRef)jpeg, NULL);
    
        NSDictionary *metadataNew = (__bridge NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);  
    
        NSLog(@"%@",metadataNew);
    

    and my Console shows:

        2012-04-26 14:15:37:137 ferret[2060:1799] {
            ColorModel = RGB;
            Depth = 8;
            Orientation = 6;
            PixelHeight = 1936;
            PixelWidth = 2592;
            "{Exif}" =     {
                ColorSpace = 1;
                PixelXDimension = 2592;
                PixelYDimension = 1936;
            };
            "{JFIF}" =     {
                DensityUnit = 0;
                JFIFVersion =         (
                    1,
                    1
                );
                XDensity = 1;
                YDensity = 1;
            };
            "{TIFF}" =     {
                Orientation = 6;
            };
        }
    

    No latitude/longitude.