Click here to Skip to main content
Click here to Skip to main content

ExifLib - A Fast Exif Data Extractor for .NET 2.0+

, 23 Jul 2014
Rate this:
Please Sign up or sign in to vote.
Reads JPEG Exif data without the heavyweight and unnecessary instantiation of GDI+ objects.

Exif Lib - test application

Introduction

ExifLib simply reads Exif tags (i.e., camera model, GPS data, date picture taken, shutter speed etc.) from JPEG files, without the overhead introduced by using the GDI+ classes located in System.Drawing.Imaging, and with less lines of code for the developer.

Background

I've been using a simple command line application to move my photos into subdirectories based on the date on which they were created. As with all other .NET Exif implementations I've seen, I was using the PropertyItem class located in System.Drawing.Imaging. While this does the job, I often found myself processing thousands of images at a time, and the .NET classes were just too slow for the job. ExifLib goes back to the JPEG/TIFF standard itself, and only reads the essentials, using little more than the file input classes in System.IO.

Using the Code

ExifLib is very simple, with only one class and one enum in the namespace. Just add a reference to ExifLib.dll, and you're good to go! An example follows:

using ExifLib;
...
...
...
// Instantiate the reader
using (ExifReader reader = new ExifReader(@"C:\temp\testImage.jpg"))
{
    // Extract the tag data using the ExifTags enumeration
    DateTime datePictureTaken;
    if (reader.GetTagValue<DateTime>(ExifTags.DateTimeDigitized, 
                                    out datePictureTaken))
    {
        // Do whatever is required with the extracted information
        MessageBox.Show(this, string.Format("The picture was taken on {0}", 
           datePictureTaken), "Image information", MessageBoxButtons.OK);
    }
}

Note that the ExifReader class holds the image file open, so once you're finished with the reader, be sure to call its Dispose method, either explicitly, or implicitly through a using statement (as in the above example).

How it works

Exif data is stored in the JPEG header, inside the APP1 block. This block contains a number of IFDs (image file directories). These include the EXIF IFD and the GPS IFD, which contain the tags available for retrieval by this library.

The IFDs start with a catalogue of EXIF tags and the stream offsets to where the data for each tag is stored. On instantiation, the library creates a Dictionary of these tag offsets, which are accessed during retrieval of a specific tag's value. It's this lazy retrieval which gives the library its speed, as most EXIF use-cases only involve retrieving a handful of tag values, so there's little use in retrieving tag values before they're required.

Points of Interest

Something strange that I learned while writing this library is that while JPEG stipulates "Big Endian" encoding (i.e., numbers read from left to right), the TIFF standard allows Big or Little Endian encoding. Since the Exif tags are encoded using TIFF encoding, often the JPEG will be read using "Big Endian" encoding until the TIFF section is reached, at which point the encoding reverses and the rest of the document is read using "Little Endian" encoding.

During coding, I realised from a comment on the ExifWorks CodeProject article that it's possible to increase performance when using System.Drawing.Image by setting the constructor's validateImageData parameter to false. However, even when using this enhancement, ExifLib still performs 50% faster, possibly because it does not read the tag values until they're requested. I have also noticed that ExifLib performs similarly with small (<1MP) images, but scales better when loading larger images. The screenshot at the top of this page was produced using a 12MP image.

History

Version 1.1

  • Array extraction has been added, thanks to a comment from Justin Carasick. This is used in various fields, including GPS coordinates and Exif versioning. The previous version of ExifLib would only return the first element from an array.

Version 1.2

  • Fixed bug when retrieving data for fields shorter than 4 bytes, thanks to a comment from bartsy. The previous version of ExifLib would lose important data from these fields when processing big-endian encoded files.
  • Updated the project to Visual Studio 2010, refactored a little of the code. The project is still .NET 2.0+.

Version 1.3

  • Added the ability to extract JPEG encoded thumbnails from images, thanks to a comment from StyrianOak. Note that uncompressed (i.e. TIFF) encoded thumbnails are not supported, but since any camera which supports the DCF standard will produce JPEG thumbnails, this is a minor limitation.

Version 1.4

  • Added a constructor overload to allow reading of JPEG data from any seekable stream
  • Modified code to allow compiling for Windows Phone and Silverlight. The NuGet package now includes Windows Phone and Silverlight DLLs.
  • Improved support for null DateTime values thanks to comments from schurig and BrandonOrding
  • undefined Exif fields are now returned as byte[] instead of uint[]
  • Fixed a bug in the thumbnail extractor where thumbnails with 0xFF padding were not being recognised, thanks to a comment from _d-fens_.
  • Added the option to retrieve a TIFF rational as an int[] {numerator, denominator} array (instead of double), thanks to a comment from Member 10226163.
  • Changed thumbnail padding detection code to accept 0x00 as well as 0xFF as padding bytes, thanks to a comment from Cruiser77
  • Added conditional compilation options for Windows Store app compatibility, thanks to a comment from _dieQueeQ.

Version 1.5

  • Fixed an exception when reading images containing tags without datatypes
  • Refactored to store tag data in separate dictionaries for each IFD
  • Added the ability to extract metadata from images which don't contain the EXIF sub IFD, thanks to a task raised in workspaces by Charlie Hess

Version 1.6

  • On frameworks prior to 4.5, an exception thrown while initialising the reader can result in the stream being closed. Added code for 4.5+ to prevent this from happening
  • Added a new constructor parameter for framework 4.5+ to allow the user to indicate that the supplied stream should be left open when the reader is disposed
  • Added checking for streams which report CanSeek as true, but don't actually seek

NuGet Release

ExifLib is now available on nuget! Simply install from the Visual Studio Package Manager Console using Install-Package ExifLib.

License

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

Share

About the Author

Simon McKenzie
Software Developer BreastScreen Victoria
Australia Australia

Simon McKenzie has been working as a developer for 10 years, primarily in .NET, with interests in imaging and GIS, particularly on mobile platforms. He is the author of the award winning MapSnap GPS, a moving map application for Windows Phone. He's also the author of the popular (free) high-speed ExifLib EXIF extractor for .NET.


Comments and Discussions

 
QuestionWorking out the Flash value Pinmemberkramware29-Jul-14 19:21 
AnswerRe: Working out the Flash value [modified] PinpremiumSimon McKenzie29-Jul-14 19:46 
GeneralRe: Working out the Flash value Pinmemberkramware29-Jul-14 20:41 
Questionmetadata of video files Pinmemberdavidcole28-Jul-14 12:28 
AnswerRe: metadata of video files PinpremiumSimon McKenzie28-Jul-14 12:35 
QuestionGreat work / intriguing usages PinpremiumB. Clay Shannon22-Jul-14 8:49 
BugBug: the stream is altered when no Exif data can be found Pinmembertubededentifrice21-Jul-14 15:44 
GeneralRe: Bug: the stream is altered when no Exif data can be found Pinmembertubededentifrice21-Jul-14 15:48 
GeneralRe: Bug: the stream is altered when no Exif data can be found PinpremiumSimon McKenzie21-Jul-14 16:08 
GeneralRe: Bug: the stream is altered when no Exif data can be found Pinmembertubededentifrice22-Jul-14 15:40 
GeneralRe: Bug: the stream is altered when no Exif data can be found [modified] PinpremiumSimon McKenzie22-Jul-14 15:54 
GeneralRe: Bug: the stream is altered when no Exif data can be found PinpremiumSimon McKenzie21-Jul-14 15:58 
GeneralRe: Bug: the stream is altered when no Exif data can be found PinpremiumSimon McKenzie21-Jul-14 18:59 
GeneralRe: Bug: the stream is altered when no Exif data can be found Pinmembertubededentifrice22-Jul-14 15:38 
QuestionNOOB - Need some help PinmemberMember 1088498515-Jun-14 7:03 
AnswerRe: NOOB - Need some help PinpremiumSimon McKenzie15-Jun-14 13:12 
GeneralRe: NOOB - Need some help PinmemberMember 1088498515-Jun-14 13:45 
GeneralRe: NOOB - Need some help PinpremiumSimon McKenzie15-Jun-14 13:52 
GeneralRe: NOOB - Need some help PinmemberMember 1088498515-Jun-14 14:00 
GeneralMy vote of 5 PinpremiumVolynsky Alex18-May-14 4:58 
QuestionGPS coordinates not accurate PinmemberNerijus_Vax6-May-14 5:36 
AnswerRe: GPS coordinates not accurate PinpremiumSimon McKenzie6-May-14 13:11 
Hi,
 
Firstly, how are you obtaining the coordinates in your example? Do you get the same results using a tool like Exif Viewer? I ask this because .07 degrees comes out to approximately 2 metres (110 * .07 / 3.6, see here for details), which is more than standard GPS accuracy (15 metres), so it's unlikely that your image would store coordinates with this level of accuracy.
 
ExifLib extracts the exact raw data from the JPEG, so 51, 20, 35 is exactly what's in your EXIF. I suspect that whatever tool you used to get the 51;20;35.07000000000069 result did a conversion from DMS to DDD and back again, producing floating point errors in the conversion. Here's an example of how this can happen:
var coord = 51F + 20F/60 + 35F/3600;
Console.WriteLine((coord * 3600D) % 60);
> 35.0006103515625
I hope this helps.
 
Regards,
 
Simon
QuestionCannot get JPEG image metadata Pinmemberxzhang25-Apr-14 5:51 
AnswerRe: Cannot get JPEG image metadata PinpremiumSimon McKenzie25-Apr-14 12:53 
QuestionWrite exif data in jpeg image Pinmemberdiaconu1324-Mar-14 4:14 
AnswerRe: Write exif data in jpeg image PinpremiumSimon McKenzie24-Mar-14 13:46 
GeneralRe: Write exif data in jpeg image Pinmemberdiaconu1328-Mar-14 10:57 
QuestionUnable to locate Exif data Pinmemberkketterman14-Mar-14 3:52 
AnswerRe: Unable to locate Exif data PinpremiumSimon McKenzie15-Jun-14 13:17 
QuestionNeed help getting it started in VS 2010 PinmemberJohn9703016-Feb-14 13:18 
AnswerRe: Need help getting it started in VS 2010 PinmemberSimon McKenzie16-Feb-14 16:11 
GeneralRe: Need help getting it started in VS 2010 PinmemberJohn9703017-Feb-14 18:48 
GeneralRe: Need help getting it started in VS 2010 PinmemberSimon McKenzie17-Feb-14 18:53 
GeneralRe: Need help getting it started in VS 2010 PinmemberJohn9703018-Apr-14 14:11 
GeneralRe: Need help getting it started in VS 2010 PinmemberJohn9703019-Apr-14 10:00 
GeneralRe: Need help getting it started in VS 2010 PinmemberJohn9703019-Apr-14 10:11 
GeneralRe: Need help getting it started in VS 2010 PinpremiumSimon McKenzie21-Apr-14 13:44 
BugToo big picture? PinmemberMember 105770116-Feb-14 6:40 
GeneralRe: Too big picture? PinmemberSimon McKenzie6-Feb-14 11:27 
GeneralRe: Too big picture? PinmemberMember 105770117-Feb-14 4:28 
QuestionError using exiflib [modified] PinmemberMember 1055565029-Jan-14 0:34 
AnswerRe: Error using exiflib PinmemberSimon McKenzie29-Jan-14 9:54 
GeneralRe: Error using exiflib PinmemberMember 1055565029-Jan-14 12:54 
GeneralRe: Error using exiflib PinmemberSimon McKenzie29-Jan-14 13:04 
GeneralRe: Error using exiflib PinmemberMember 1055565029-Jan-14 23:24 
GeneralRe: Error using exiflib PinmemberSimon McKenzie30-Jan-14 11:32 
QuestionGPS Data PinmemberJason Podwojski16-Jan-14 2:20 
AnswerRe: GPS Data [modified] PinmemberSimon McKenzie16-Jan-14 8:32 
AnswerRe: GPS Data PinmemberMember 1055565029-Jan-14 1:26 
QuestionWP8 Camera Roll - Access Denied PinmemberJason Podwojski13-Jan-14 11:05 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 24 Jul 2014
Article Copyright 2009 by Simon McKenzie
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid