When you take a picture today your digital camera, something is stored in the JPG file other than the image itself: digital cameras store information such as camera model, date taken, metering mode, focal length shutter speed and in some cases a small thumbnail image; some news agencies, such as Reuters (see chopper.jpg image in this example) also add comments and other information. In this article we’ll show how to read this information using the new classes in WPF’s System.Windows.Media namespace.
Metadata that is associated with an image is data that describes the image but that is not necessary for display of the image.
Some image formats (such as JPEG, PNG, TIFF, PSD and others) support one or more metadata formats, and the way this information can be read differs from format to format. WPF’s new classes allows you to read this information without having to worry about the underlying format, always using the same piece code. Windows Presentation Foundation supports the following metadata schemas: Exchangeable image file (Exif), International Press Telecommunications Council (IPTC), Extensible Metadata Platform (XMP), tEXt (PNG Textual Data) and image file directory (IFD).
To read metadata you need to insert first a reference to the PresentationCore assembly to your project: this assembly contains the System.Windows.Media namespace that we will use. Now, lets walk thru the example code, step by step. First you need to open the image, using the BitmapFrame.Create constructor:
BitmapSource img = BitmapFrame.Create(new Uri(filename));
The BitmapSource img instance contains a property that has an instance of BitmapMetadata called "Metadata". This is where all the metadata is contained:
BitmapMetadata meta = (BitmapMetadata)img.Metadata; Console.WriteLine(" metadata\n Type: {0}",meta.GetType()); Console.WriteLine(" Title: {0}", meta.Title); Console.WriteLine(" Subject: {0}", meta.Subject); Console.WriteLine(" Comment: {0}", meta.Comment); Console.WriteLine(" Date taken: {0}", meta.DateTaken); Console.WriteLine(" Camera: {0} {1}",meta.CameraManufacturer,meta.CameraModel); Console.WriteLine(" Copyright: {0}", meta.Copyright);
Image dimensions are not a part of metadata, these are stored directly in the "img" instance:
double mpixel = (img.PixelHeight * img.PixelWidth)/(double)1000000; Console.WriteLine(" Pixelsize {0}x{1} ({2} megapixels)", img.PixelWidth, img.PixelHeight,mpixel); Console.WriteLine(" DPI {0}x{1}", img.DpiX, img.DpiY);
Its as simple as this, just instantiate the BitmapSource and read the Metadata property.
Now, lets put it all together: Create a new Console Application project in Visual Studio. Add a reference to the PresentationCore assembly and write/paste the following code inside the "Program" class, replacing the default "Main" function:
static void readMetadata(string filename) { BitmapSource img = BitmapFrame.Create(new Uri(filename)); /* Image data */ double mpixel = (img.PixelHeight * img.PixelWidth)/(double)1000000; Console.WriteLine(" Pixelsize {0}x{1} ({2} megapixels)", img.PixelWidth, img.PixelHeight,mpixel); Console.WriteLine(" DPI {0}x{1}", img.DpiX, img.DpiY); /* Image metadata */ BitmapMetadata meta = (BitmapMetadata)img.Metadata; Console.WriteLine(" metadata\n Type: {0}",meta.GetType()); Console.WriteLine(" Title: {0}", meta.Title); Console.WriteLine(" Subject: {0}", meta.Subject); Console.WriteLine(" Comment: {0}", meta.Comment); Console.WriteLine(" Date taken: {0}", meta.DateTaken); Console.WriteLine(" Camera: {0} {1}",meta.CameraManufacturer,meta.CameraModel); Console.WriteLine(" Copyright: {0}", meta.Copyright); StringBuilder authors = new StringBuilder(); if (meta.Author != null) { foreach (string author in meta.Author) { authors.Append(author + "; "); } Console.WriteLine(" Author(s): {0}", authors.ToString()); } Console.WriteLine(" Rating: {0}", meta.Rating); StringBuilder keyWords = new StringBuilder(); if (meta.Keywords!=null) { foreach (string keyword in meta.Keywords) { keyWords.Append(keyword+"; "); } Console.WriteLine(" Keywords: {0}", keyWords.ToString()); } Console.WriteLine(""); } static void Main(string[] args) { Console.WriteLine("Tryexcept.com Image metadata example"); /* Get info from all files in c:\pictures */ DirectoryInfo di = new DirectoryInfo(@"c:\pictures"); /* Only JPEG files */ FileInfo[] files = di.GetFiles("*.jpg"); foreach (FileInfo fi in files) { Console.WriteLine(fi.Name); Program.readMetadata(fi.FullName); } Console.ReadLine(); } }
Copy a couple of JPG images to the c:\pictures folder and run the project. The output should be something like this:
The Windows Vista Explorer uses these classes to access image metadata as well. It also uses the InPlaceBitmapMetadataWriter to add or edit tags and to edit the image rating. InPlaceBitmapMetadataWriter allows you to edit or create metadata without changing the image contents in any way, avoiding the quality-loss effect that happens when you re-save a JPEG image.
In the screenshot you can see the DSCF1852.JPG image selected along with some of the metadata below: compare it with the previous screenshot to see the same information as output from our example.
Downloads: example JPEG images from this example, example source code or compiled imagemetadata.exe.
Leave a Reply