Click here to Skip to main content
15,884,177 members
Articles / Programming Languages / C# 4.0
Tip/Trick

C#: Display Photo Taken Location on a Map in Windows

Rate me:
Please Sign up or sign in to vote.
4.72/5 (11 votes)
11 Dec 2013CPOL3 min read 47.2K   2.9K   39   12
Smart phones all seem to geo tag (add GPS details) to the photos they take. However, after you copy that photo to your PC it is difficult to see, in human terms, where that photo was taken. This project parses the photo for the GPS data and opens that location on a map.

Image 1

Introduction

This Windows Desktop application takes a picture as an input parameter and if that picture has GPS meta data, it will open the location that picture was taken in Google Maps (configurable to other mapping sites or applications). Smart phones seem to do this well, but once you have copied the picture to your desktop/laptop, it is somewhat difficult to see where the photo was taken. If the image does not have GPS data encoded in its metadata, or the file type passed in is not an image, a pop-up error explains the problem. To make using this easier, leave it on your desktop and drag and drop photos on to it, or wire it up as an alternative opener for photo files (see sample image).

Background

Almost all of the code to make this happen is available elsewhere, either in MSDN or on CodeProject, this just ties all the pieces together into a usable package. Some notable resources: ExIF Wiki[^], Google Maps API[^], GeoCode Conversion[^], Image Properties API[^]

Using the Code

The code should compile and run without intervention. If you would like to extend the code for your own use, focus on the two classes that encapsulate most of the work, Coord.cs and GeoPoint.cs.

The key points to note:

  1. On startup (Program.cs), we parse the command line for the path to a valid picture file.
  2. In GeoPoint.GetFromImageFile(), we parse the image meta data for GPS details.
  3. Once we have the GPS details, we use the Coord functions to convert them to proper Longitude and Latitude.
  4. After we have the Longitude and Latitude, we construct a URL to open Google Maps to that location. Note that you can alter the URL to use any other mapping site, or since you have the coordinates, you could pass that to any mapping API of your choice.
  5. We launch the URL using the default browser.

Extending the Code

Image 2
Since I thought someone might ask about adding this to the Windows Explorer context menu for pictures, it is easy to do with SharpShell[^] (very cool project - thanks SharpShell team!). You can read the SharpShell documentation for details, but ultimately it will entail adding a ToolStripMenuItem to the shell context menu. For brevity, the error handling and debugging hooks have been removed.

C#
// The key piece of code to get the menu, or if not a valid picture file, null
private ToolStripMenuItem GetShowImageLocationMenu()
{
      // SelectedItemPaths is a property of SharpShell's SharpContextMenu
    string selected_file = SelectedItemPaths.FirstOrDefault();
    
    if (IsImage(selected_file))
    {

        var imageLocationRootMenu = new ToolStripMenuItem("Show Picture Location");
        imageLocationRootMenu.ToolTipText = "Show location picture was taken on a map.";
        imageLocationRootMenu.Click += new EventHandler((o, e) =>
        {
                    // On menu click, try to display the image locaion, or display errors if needed
            string messages = ShowPictureLocationLib.ShowPictureLocationHelper.ShowLocation(selected_file);
            if (!String.IsNullOrEmpty(messages))
            {
                Msg.Box(messages, "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        });
        return imageLocationRootMenu;
    }
    return null;
}

// Code to aid in identifying ExIF images
public static bool IsImage(string path_to_file)
{
    if (String.IsNullOrEmpty(path_to_file) || !File.Exists(path_to_file))
    {
        return false;
    }

    string ext = (Path.GetExtension(path_to_file) ?? "")
        .TrimStart('.')
        .ToLower();

    // Extensions based on this article:
    // http://en.wikipedia.org/wiki/Exchangeable_image_file_format
    return (new string[] { "jpg", "jpeg", "png", "tiff", "gif" })
        .Contains(ext);
}

History

  • 10 October 2013 - Initial draft (1.0)  
  • 19 October 2013 - Updated source breaking most of the code into a reusable library. Added support for storing the map URL in a config file. Improved error management.  
  • 20 October 2013 - Updated with details on adding to Windows Explorer context menu
  • 21 October 2013 - Fixed bug were I was using Longitude in place of Latitude, terribly sorry about that.  
  • 11 December 2013 - Updated some notes in the article. Code is unchanged.
  • 06 February 2015 - Several small updates based on Piyush Man's input, including:

    • Included Saver.dll in project outside of references (/Lib/ folder) so it won't get lost.
    • Included test images.
    • Removed debugging command line parameter (default parameter passed in used when launching the .exe from Visual Studio in a debug build)
    • Altered the default URL to pass geo codes, not longitude and latitude to Google Maps.
    • Was less aggressive in removing /bin/ and /obj/ folders in posted code (which is why Saver.dll was missing in the previous posting - sorry).
    Thanks Piyush!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionIt trows parameter error Pin
Piyush Manharlal4-Feb-15 7:23
Piyush Manharlal4-Feb-15 7:23 
AnswerRe: It trows parameter error Pin
Brad Joss6-Feb-15 15:49
professionalBrad Joss6-Feb-15 15:49 
AnswerRe: It trows parameter error Pin
Brad Joss6-Feb-15 17:00
professionalBrad Joss6-Feb-15 17:00 
GeneralMy vote of 5 Pin
JV999912-Dec-13 2:21
professionalJV999912-Dec-13 2:21 
QuestionLinks Reversed Pin
Charles L. Enders23-Oct-13 11:06
professionalCharles L. Enders23-Oct-13 11:06 
AnswerRe: Links Reversed Pin
Brad Joss23-Oct-13 15:32
professionalBrad Joss23-Oct-13 15:32 
Questionneed a closer look Pin
ledtech320-Oct-13 14:17
ledtech320-Oct-13 14:17 
Questioncool tool Pin
bryce20-Oct-13 13:26
bryce20-Oct-13 13:26 
AnswerBug Fixed. Pin
Brad Joss21-Oct-13 9:24
professionalBrad Joss21-Oct-13 9:24 
GeneralRe: Bug Fixed. Pin
Liam O'Hagan21-Oct-13 17:19
Liam O'Hagan21-Oct-13 17:19 
This still doesn't work for me, when I drag / drop a photo, I get 3 web browser windows (Google Chrome) opening;

For example:

First window[^]

Second window (note, clicking this won't take you anywhere)

Third window (neither will this one!)

If I change your Coord class ToString override to get rid of the " character after the seconds component of the coordinate then it correctly opens in only one window;
C#
// Format that Google Maps wants
return String.Format("{0}{1}° {2}\' {3}",
    MinusDirection ? "-" : "+",
    Degree,
    Minute,
    Second
    );

Correct geolocation[^]
I have no blog...

SuggestionRe: Bug Fixed. Pin
Brad Joss22-Oct-13 8:28
professionalBrad Joss22-Oct-13 8:28 
SuggestionCode updated - Coord format mask now configurable Pin
Brad Joss22-Oct-13 19:03
professionalBrad Joss22-Oct-13 19:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.