C# Exif code - sample usage

Drew Noakes has written an excellent Exif data parsing library at http://www.drewnoakes.com/code/exif/, and Ferret Renaud has ported this to C#, found at http://renaud91.free.fr/MetaDataExtractor/. I've taken Drew's sample usage and ported this to use C# syntax.

There are several ways to obtain the Metadata instance:

  1. This approach reads all types of known Jpeg metadata (at present, Exif and Iptc) in a single call. In most cases, this is the most appropriate usage. Note that in this case, I've shown the namespaces via the using keyword, as opposed to explicitly naming them. For most of the others, I've used explicit naming.
    using com.drew.metadata; using com.drew.imaging.jpg; Stream jpegFile = new FileStream(strFileName,FileMode.Open); Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
  2. This approach shows using individual MetadataReader implementations to read a file. This is less efficient than approach 1, as the file is opened and read twice.
    Metadata metadata = new Metadata(); new com.drew.metadata.exif.ExifReader(new FileInfo(strFileName)).Extract(metadata); new com.drew.metadata.iptc.IptcReader(new FileInfo(strFileName)).Extract(metadata);
  3. As fast as approach 1 (this is what goes on inside the JpegMetadataReader's readMetadata() method), this code is handy if you want to look into other Jpeg segments too.
    Stream jpegFile = new FileStream(strFileName,FileMode.Open); JpegSegmentReader segmentReader = new JpegSegmentReader(jpegFile); byte[] exifSegment = segmentReader.ReadSegment(JpegSegmentReader.SEGMENT_APP1); byte[] iptcSegment = segmentReader.ReadSegment(JpegSegmentReader.SEGMENT_APPD); Metadata metadata = new Metadata(); new com.drew.metadata.exif.ExifReader(exifSegment).Extract(metadata); new com.drew.metadata.iptc.IptcReader(iptcSegment).Extract(metadata);
  4. For this section, Drew says: "This approach is the slowest, because it decodes the Jpeg image. Of course you now have a decoded image to play with. In some instances this will be most appropriate. " It uses the Java types BufferedImage and JPEGImageDecoder, which have no direct equivaents in C#, so I don't believe this will work.
    // Don't believe this works in the windows version /* JPEGImageDecoder jpegDecoder = JPEGCodec.createJPEGDecoder(new FileInputStream(jpegFile)); BufferedImage image = jpegDecoder.decodeAsBufferedImage(); // now you can use the image JPEGDecodeParam decodeParam = jpegDecoder.getJPEGDecodeParam(); Metadata metadata = JpegMetadataReader.readMetadata(decodeParam); */

Once you have the Metadata object, you can use it like this:

// iterate through metadata directories IEnumerator directories = metadata.GetDirectoryIterator(); while (directories.MoveNext()) { com.drew.metadata.Directory directory = (com.drew.metadata.Directory)directories.Current; // iterate through tags and print to System.out IEnumerator tags = directory.GetTagIterator(); while (tags.MoveNext()) { Tag tag = (Tag)tags.Current; // use Tag.toString() Console.WriteLine(tag); } }

The Tag class has other methods you can use to customise the output:

int iType = tag.GetTagType(); string strHex = tag.GetTagTypeHex(); string strName = tag.GetTagName(); string strDesc = tag.GetDescription();

tag.getDescription() returns a string. You can get the tag's value in its original type using the Directory instance. For example:

com.drew.metadata.Directory exifDirectory = metadata.GetDirectory(typeof(com.drew.metadata.exif.ExifDirectory)); int iVal = exifDirectory.GetInt(tag.GetTagType()); double dVal = exifDirectory.GetDouble(tag.GetTagType()); float fVal = exifDirectory.GetFloat(tag.GetTagType()); long lVal = exifDirectory.GetLong(tag.GetTagType()); string strVal = exifDirectory.GetString(tag.GetTagType()); com.drew.lang.Rational ratVal = exifDirectory.GetRational(tag.GetTagType()); DateTime dtVal = exifDirectory.GetDate(tag.GetTagType());

Note that exceptions will be thrown if attempting to convert between significantly different types, such as GetDate where the value is a float.

Alternatively, you can search for a specific tag in a specific directory:

com.drew.metadata.Directory exifDirectory = metadata.GetDirectory(typeof(com.drew.metadata.exif.ExifDirectory)); string cameraMake = exifDirectory.GetString(com.drew.metadata.exif.ExifDirectory.TAG_MAKE); string cameraModel = exifDirectory.GetString(com.drew.metadata.exif.ExifDirectory.TAG_MODEL); com.drew.metadata.Directory iptcDirectory = metadata.GetDirectory(typeof(com.drew.metadata.exif.ExifDirectory)); string caption = iptcDirectory.GetString(com.drew.metadata.iptc.IptcDirectory.TAG_CAPTION);