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:
- 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);
- 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);
- 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);
- 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);