Created
August 8, 2012 09:39
-
-
Save 5342/3293802 to your computer and use it in GitHub Desktop.
Quick hack to find and extract GPS exif data from all jpg files in a given path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Drawing; | |
using System.Diagnostics; | |
using System.Collections.Generic; | |
namespace LocationExtractor | |
{ | |
/// <summary> | |
/// Version 0.0 Initial version, This was hacked together over a few beers, and is no way complete or correct, it just accomplished the task required at the time. | |
/// version 0.1 Used Image.FromStream as aposed to Image.FromFile it caused some strange errors opening some files | |
/// Added some extra error checking on opening images and for zero denominator | |
/// </summary> | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
if(args.Length != 1 || !Directory.Exists(args[0])) | |
{ | |
Console.WriteLine("Usage\r\nLocationExtractor path"); | |
return; | |
} | |
ExtractData(args[0]); | |
Console.ReadLine(); | |
} | |
private static void ExtractData(string folder) | |
{ | |
try | |
{ | |
foreach (var file in Directory.GetFiles(folder)) | |
{ | |
if (file.ToLower().EndsWith(".jpg") || file.ToLower().EndsWith(".jpeg")) | |
{ | |
ExtractLocation(file); | |
} | |
} | |
foreach (var directory in Directory.GetDirectories(folder)) | |
{ | |
ExtractData(directory); | |
} | |
} | |
catch (UnauthorizedAccessException) { /*Ignore*/} // Stuff we do not have access to | |
catch (DirectoryNotFoundException) { /*Ignore*/} // Symbolic links that are invalid | |
} | |
private static void ExtractLocation(string file) | |
{ | |
if (file.ToLower().EndsWith("jpg") || file.ToLower().EndsWith("jpeg")) | |
{ | |
Image image = null; | |
try | |
{ | |
Console.Title = file; | |
try | |
{ | |
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read); | |
image = Image.FromStream(fs); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("Error opening {0} image may be corupted, {1}", file, ex.Message); | |
return; | |
} | |
// GPS Tag Names | |
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/GPS.html | |
// Check to see if we have gps data | |
if (Array.IndexOf<int>(image.PropertyIdList, 1) != -1 && | |
Array.IndexOf<int>(image.PropertyIdList, 2) != -1 && | |
Array.IndexOf<int>(image.PropertyIdList, 3) != -1 && | |
Array.IndexOf<int>(image.PropertyIdList, 4) != -1) | |
{ | |
string gpsLatitudeRef = BitConverter.ToChar(image.GetPropertyItem(1).Value, 0).ToString(); | |
string latitude = DecodeRational64u(image.GetPropertyItem(2)); | |
string gpsLongitudeRef = BitConverter.ToChar(image.GetPropertyItem(3).Value, 0).ToString(); | |
string longitude = DecodeRational64u(image.GetPropertyItem(4)); | |
Console.WriteLine("{0}\t{1} {2}, {3} {4}", file, gpsLatitudeRef, latitude, gpsLongitudeRef, longitude); | |
} | |
} | |
catch (Exception ex) { Console.WriteLine("Error processign {0} {1}", file, ex.Message); } | |
finally | |
{ | |
if(image != null) image.Dispose(); | |
} | |
} | |
} | |
private static string DecodeRational64u(System.Drawing.Imaging.PropertyItem propertyItem) | |
{ | |
uint dN = BitConverter.ToUInt32(propertyItem.Value, 0); | |
uint dD = BitConverter.ToUInt32(propertyItem.Value, 4); | |
uint mN = BitConverter.ToUInt32(propertyItem.Value, 8); | |
uint mD = BitConverter.ToUInt32(propertyItem.Value, 12); | |
uint sN = BitConverter.ToUInt32(propertyItem.Value, 16); | |
uint sD = BitConverter.ToUInt32(propertyItem.Value, 20); | |
decimal deg; | |
decimal min; | |
decimal sec; | |
// Found some examples where you could get a zero denominator and no one likes to devide by zero | |
if (dD > 0) { deg = (decimal)dN / dD; } else { deg = dN; } | |
if (mD > 0) { min = (decimal)mN / mD; } else { min = mN; } | |
if (sD > 0) { sec = (decimal)sN / sD; } else { sec = sN; } | |
if (sec == 0) return string.Format("{0}° {1:0.###}'", deg, min); | |
else return string.Format("{0}° {1:0}' {2:0.#}\"", deg, min, sec); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment