During one of my ASP.NET Core classes I made demo about how to read GPS coordinates from photo and display location on a map. I took my favorite photo of beer kiosk in Krakow and displayed location of this kiosk on map. This blog post describes my experiment on getting GPS coordinates from EXIF data in ASP.NET Core application.
Wikipedia defines EXIF (Exchangeable image file format) as a standard that specifies the formats for images, sound, and ancillary tags used by digital cameras (including smartphones), scanners and other systems handling image and sound files recorded by digital cameras. Most of modern devices used to take photos save meta information in EXIF format to photos. It’s great but be aware – not all people may use this information in good purposes.
Reading EXIF data
There are some libraries available for ASP.NET Core for reading EXIF data from photos. For this demo I decided to use some library that deals only with EXIF data, My choice was NuGet package called ExifLib.Standard.It’s simple to use, kind of primitive and basic, but it works well and does its job.
Here is the sample how to read some EXIF fields.
using (var reader = new ExifReader("my-image.jpg"))
{
reader.GetTagValue(ExifTags.DigitalZoomRatio, out double brightness);
reader.GetTagValue(ExifTags.DateTimeDigitized, out DateTime photoDate);
}
Best thing about ExifLib.Standard – it works reasonably fast also with bigger photos (I tried few ones that are ~7 MB). Some libraries got extremely slow with photos bigger than 3 MB but ExifLib.Standard seems survive well.
Reading GPS coordinates
Getting GPS coordinates is a little tricky as coordinates are given back as an array of doubles containing degree, minute and second. This is not shortcut done by library developer but this is how devices save coordinates.
For me this information was enough to get done with what I was up to.
Maps used on web pages usually need coordinates as real numbers. Getting components of coordinates to real number is easy. First number is degree, second one is minutes and third one seconds. Latitude can be transformed to real number using the following calculation:
latitudeReal = latitude[0] + latitude[1] / 60 + latitude[2] / 3600
Based on this I developed some extension methods to make reading of coordinates easier.
public static class ExifLibExtensions
{
public static double? GetLatitude(this ExifReader reader)
{
return reader.GetCoordinate(ExifTags.GPSLatitude);
}
public static double? GetLongitude(this ExifReader reader)
{
return reader.GetCoordinate(ExifTags.GPSLongitude);
}
private static double? GetCoordinate(this ExifReader reader, ExifTags type)
{
if (reader.GetTagValue(type, out double[] coordinates))
{
return ToDoubleCoordinates(coordinates);
}
return null;
}
private static double ToDoubleCoordinates(double[] coordinates)
{
return coordinates[0] + coordinates[1] / 60f + coordinates[2] / 3600f;
}
}
These methods are actually simple but it’s the good task for students to work these out.
Creating model for photo coordinates
To get data to browser we need a model for it. This model must carry coordinates – if available – and also error information if something went wrong when reading EXIF data. Here is the model I created.
public class PhotoCoordinatesModel
{
public double? Lat { get; set; }
public double? Lon { get; set; }
public string Error { get; set; }
public bool HasValidCoordinates()
{
return Lat.HasValue && Lon.HasValue;
}
}
And here is my demo controller action that reads EXIF data.
public IActionResult Index()
{
var model = new PhotoCoordinatesModel();
try
{
using (var reader = new ExifReader("my-photo.jpg"))
{
model.Lat = reader.GetLatitude();
model.Lon = reader.GetLongitude();
}
}
catch(ExifLibException exifex)
{
model.Error = exifex.Message;
}
return View(model);
}
Thanks to extension methods I created before the code in controller action is clean and minimal.
And here’s the end result. My favorite beer barrel in Krakow located on map. Excellent!
Wrapping up
There are not many graphic libraries available for ASP.NET Core but if we need only EXIF data then we have some options.After trying some libraries I decided to go with ExifLib.Standard as it was minimalistic and performed well. Reading EXIF data is easy using this library. After writing some extension methods to get latitude and longitude of photo we god pretty clean controller action to display photo location on map.
View Comments (1)
Thanks for your help