How to Fetch the Geotag details of the captured image or stored image in Windows phone 8

12,846

Solution 1

You will need to read the EXIF data from the image.

You can use a library such as this

// Instantiate the reader
ExifReader reader = new ExifReader(@"..path to your image\...jpg");

// Extract the tag data using the ExifTags enumeration
double gpsLat, gpsLng;
if (reader.GetTagValue<double>(ExifTags.GPSLatitude, 
                                    out gpsLat))
{
    // Do whatever is required with the extracted information
    //...
}
if (reader.GetTagValue<double>(ExifTags.GPSLongitude, 
                                    out gpsLng))
{
    // Do whatever is required with the extracted information
    //...
}

UPDATE. Code changed to use MemoryStream

    void cam_Completed(object sender, PhotoResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            using (MemoryStream memo = new MemoryStream())
            {
                e.ChosenPhoto.CopyTo(memo);
                memo.Position = 0;
                using (ExifReader reader = new ExifReader(memo))
                {
                    double[] latitudeComponents;
                    reader.GetTagValue(ExifTags.GPSLatitude, out latitudeComponents);

                    double[] longitudeComponents;
                    reader.GetTagValue(ExifTags.GPSLongitude, out longitudeComponents);

                    // Lat/long are stored as D°M'S" arrays, so you will need to reconstruct their values as below:
                    var latitude = latitudeComponents[0] + latitudeComponents[1] / 60 + latitudeComponents[2] / 3600;
                    var longitude = longitudeComponents[0] + longitudeComponents[1] / 60 + longitudeComponents[2] / 3600;

                    // latitude and longitude should now be set correctly...
                }
            }
        }
    }

Solution 2

None of these answers seemed to be completely working and correct. Here's what I came up with using this EXIF library, which is also available as a NuGet package.

public static double[] GetLatLongFromImage(string imagePath)
{
    ExifReader reader = new ExifReader(imagePath);

    // EXIF lat/long tags stored as [Degree, Minute, Second]
    double[] latitudeComponents;
    double[] longitudeComponents;

    string latitudeRef; // "N" or "S" ("S" will be negative latitude)
    string longitudeRef; // "E" or "W" ("W" will be a negative longitude)

    if (reader.GetTagValue(ExifTags.GPSLatitude, out latitudeComponents)
        && reader.GetTagValue(ExifTags.GPSLongitude, out longitudeComponents)
        && reader.GetTagValue(ExifTags.GPSLatitudeRef, out latitudeRef)
        && reader.GetTagValue(ExifTags.GPSLongitudeRef, out longitudeRef))
    {

        var latitude = ConvertDegreeAngleToDouble(latitudeComponents[0], latitudeComponents[1], latitudeComponents[2], latitudeRef);
        var longitude = ConvertDegreeAngleToDouble(longitudeComponents[0], longitudeComponents[1], longitudeComponents[2], longitudeRef);
        return new[] { latitude, longitude };
    }

    return null;
}

Helpers:

public static double ConvertDegreeAngleToDouble(double degrees, double minutes, double seconds, string latLongRef)
{
    double result = ConvertDegreeAngleToDouble(degrees, minutes, seconds);
    if (latLongRef == "S" || latLongRef == "W")
    {
        result *= -1;
    }
    return result;
}

public static double ConvertDegreeAngleToDouble(double degrees, double minutes, double seconds)
{
    return degrees + (minutes / 60) + (seconds / 3600);
}

Credit to Igor's answer for the helper method and geedubb's for the main method.

Solution 3

In my PhotoTimeline wp8 app I use this ExifLib and the following code

var info = ExifReader.ReadJpeg(stream, picture.Name);
latitude = Utils.ConvertDegreeAngleToDouble(info.GpsLatitude[0], info.GpsLatitude[1], info.GpsLatitude[2], info.GpsLatitudeRef);
longitude = Utils.ConvertDegreeAngleToDouble(info.GpsLongitude[0], info.GpsLongitude[1], info.GpsLongitude[2], info.GpsLongitudeRef);

with the helper function defined as

public static double ConvertDegreeAngleToDouble(double degrees, double minutes, double seconds, ExifGpsLatitudeRef   exifGpsLatitudeRef)
{
    double result = ConvertDegreeAngleToDouble(degrees, minutes, seconds);
    if (exifGpsLatitudeRef == ExifGpsLatitudeRef.South)
    {
        result = -1*result;
    }
    return result;
}               

public static double ConvertDegreeAngleToDouble(double degrees, double minutes, double seconds)
{            
    return degrees + (minutes/60) + (seconds/3600);
}

Solution 4

I remember that the PhotoResult you got from the chooser does not have the GPS info. But there's a workaround to get the taken photo with GPS on WP8. According to http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006(v=vs.105).aspx

On Windows Phone 8, if the user accepts a photo taken with the camera capture task, the photo is automatically saved to the phone’s camera roll.

So what you have to do is taking the last photo in MediaLibrary instead of using the PhotoResult.

// For WP8, the taken photo inside a app will be automatically saved.
// So we take the last picture in MediaLibrary.
using (MediaLibrary library = new MediaLibrary())
{
    string filePath = "x.jpg";
    MemoryStream fileStream = new MemoryStream();// MemoryStream does not need to call Close()
    Picture photoFromLibrary = library.Pictures[library.Pictures.Count - 1];// Get last picture
    Stream stream = photoFromLibrary.GetImage();
    stream.CopyTo(fileStream);
    SaveMemoryStream(fileStream, filePath);
}

private void SaveMemoryStream(MemoryStream ms, string path)
{
    try
    {
        using (var isolate = IsolatedStorageFile.GetUserStoreForApplication())
        {
            using (IsolatedStorageFileStream file = new IsolatedStorageFileStream(path, FileMode.Create, FileAccess.Write, isolate))
            {
                ms.WriteTo(file);
            }
        }
    }
    finally
    {
        IsolatedStorageMutex.ReleaseMutex();
    }
}

The x.jpg saved in IsolatedStorage will have the GPS info and you can get it out using any library which can handle EXIF data.

Share:
12,846
Arjun Sharma
Author by

Arjun Sharma

Updated on June 04, 2022

Comments

  • Arjun Sharma
    Arjun Sharma almost 2 years

    I want to fetch the information from the image regarding the Geolocation as shown in the image below

    enter image description here

     void cam_Completed(object sender, PhotoResult e)
            {
                if (e.TaskResult == TaskResult.OK)
                {
    
                    Image cameraImage = new Image();
                    BitmapImage bImage = new BitmapImage();
    
                    bImage.SetSource(e.ChosenPhoto);
                    cameraImage.Source = bImage;
    
                    e.ChosenPhoto.Position = 0;
    
                    ExifReader reader = new ExifReader(e.ChosenPhoto);
                    double gpsLat, gpsLng;
    
                    reader.GetTagValue<double>(ExifTags.GPSLatitude,
                                                        out gpsLat))
    
                    reader.GetTagValue<double>(ExifTags.GPSLongitude,
                                                        out gpsLng))
    
    
                    MessageBox.Show(gpsLat.ToString() + "" + gpsLng.ToString());   
    
                }
            }
    

    so that we can detect location where the image was taken. Please help to find the these property.

  • Arjun Sharma
    Arjun Sharma over 10 years
    Its gives error when i supplying the stream to exif reader can u suggest please
  • Igor Ralic
    Igor Ralic over 10 years
    @ArjunSharma try setting stream Position to 0.
  • Arjun Sharma
    Arjun Sharma over 10 years
    @igrali getting error Unable to read beyond the end of the stream.
  • Arjun Sharma
    Arjun Sharma over 10 years
    Kulam I have tried but didn't fined readjpeg function can please suggest me on the version u have used
  • Igor Kulman
    Igor Kulman over 10 years
    where did you look? It is in the linked DLL lib
  • Arjun Sharma
    Arjun Sharma over 10 years
    @igorkulam I have donwaloaded the ExifLib version 1.4.7 but didnt found such funtion in that Please suggest which linked Dll lib you are talking about
  • geedubb
    geedubb over 10 years
    @ArjunSharma Please try my update. Note I could not test this, but hopefully should be close enough for what you want?
  • geedubb
    geedubb over 10 years
    @ArjunSharma is location turned on in settings > location?
  • geedubb
    geedubb over 10 years
    You could also try: igrali.com/2011/11/01/…
  • Arjun Sharma
    Arjun Sharma over 10 years
    @geedubb i am able to fetch longitude and latitude with the image saved in gallery but not with the image clicked from camera can you help me on this?
  • Charlie
    Charlie almost 10 years
    The code for calculating lat/long is actually incorrect. See @Igor Kulman's answer. You'll need to use GpsLatitudeRef and GpsLongitudeRef to distinguish between east/west and north/south.
  • Charlie
    Charlie almost 10 years
    There's some confusion because there are two separate libraries for parsing Exif metadata, with the same name (ExifLib). The first: codeproject.com/Articles/47486/…. And the second: codeproject.com/Articles/36342/…. This answer uses the first. The accepted answer seems to use the second.