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;
...
...
...
ExifReader reader = new ExifReader(@"C:\temp\testImage.jpg");
DateTime datePictureTaken;
if (reader.GetTagValue<DateTime>(ExifTags.DateTimeDigitized,
out datePictureTaken))
{
MessageBox.Show(this, string.Format("The picture was taken on {0}",
datePictureTaken), "Image information", MessageBoxButtons.OK);
}
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[]
NuGet Release
ExifLib is now available on nuget! Simply install from the Visual Studio Package Manager Console using Install-Package ExifLib.