Having read up on image file formats in Wikipedia and other places I know that all the information I need is will be stored in the image files as image metadata including the Date Created. However, I tried parsing the file details myself – a long and complex job as there are several different versions in different image file formats. So, when I found that GDI+ on Windows handles most of the messy bits I was somewhat relieved.
Starting with a new addition to the Kajabity Tools which provides all the file open/save/close functionality (it will be in the next release, coming soon) it is quite easy to build the application and display all the image details in a ListView (in Details mode). Handling the Item Activated event I open a dialog to view and edit the original image file and stored details.
I added a PictureBox control to load and display the image and a small ListView control (Details mode) to display all of the metadata (PropertyItems). Small problem when I initially tried this – the image hadn’t loaded so I got an exception that the object didn’t exist. This was easily resolved by handling the PictureBox LoadCompleted event and filling the property list then – the columns are the property Id, property type, property length and property value.
void PictureBoxLoadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { try { // The PictureBox control is pictureBox - get all the PropertyItems. PropertyItem[] propItems = pictureBox.Image.PropertyItems; foreach ( PropertyItem propItem in propItems ) { ListViewItem item = new ListViewItem( "0x" + propItem.Id.ToString( "x" ) ); item.SubItems.Add( new ListViewItem.ListViewSubItem( item, propItem.Type.ToString() ) ); item.SubItems.Add( new ListViewItem.ListViewSubItem( item, propItem.Len.ToString() ) ); // Code here to extract the value of the property item values... // The ListView control is listImageProperties. listImageProperties.Items.Add( item ); } } catch( Exception ex ) { MessageBox.Show( this, ex.Message, "Error loading image metadata" ); } }
The property value is a byte array whose contents depend on the property id and must be interpreted according to the type and length. GDI+ uses a fixed set of standardised property codes – so once you know the one(s) you need, it’s easy to fetch them. The property I need has Id 0×0132 (PropertyTagDateTime) which has a data type of 2 (PropertyTagTypeASCII – a text string) and a length of 20.
The sample code below shows how to fetch the creation date property and convert it to a DateTime.
Next, I needed to convert the text to a DateTime. The strings appear to all be formatted using colons – for example “2008:09:27 22:15:35”. I used the DateTime ParseExact method to convert it to a DateTime. Job done.
Of course there was one final problem I had to resolve – many of the pictures were taken on cameras where the date hadn’t been set – so I’m back to manually editing them. Still, it’s a lot easier with a DateTimePicker control.
The sample code below shows how to fetch the creation date property and convert it to a DateTime.
try { // GDI+ provides standardised definitions! // http://msdn.microsoft.com/en-us/library/ms534415(VS.85).aspx PropertyItem propItem = pictureBox.Image.GetPropertyItem( 0x132 ); if( propItem != null ) { System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); string text = encoding.GetString( propItem.Value, 0, propItem.Len - 1 ); CultureInfo provider = CultureInfo.InvariantCulture; DateTime dateCreated = DateTime.ParseExact( text, "yyyy:MM:d H:m:s", provider ); Debug.WriteLine( "converted " + text + " to " + dateCreated.ToString() ); } else { Debug.WriteLine( "No Property Found" ); } } catch( Exception ex ) { Debug.WriteLine( "Error: " + ex.Message ); }First, the code shows how to retrieve the value of the property with a special twist – the strings appear to end with a zero byte (like a C style string) so you need to exclude the last byte.
Next, I needed to convert the text to a DateTime. The strings appear to all be formatted using colons – for example “2008:09:27 22:15:35”. I used the DateTime ParseExact method to convert it to a DateTime. Job done.
Of course there was one final problem I had to resolve – many of the pictures were taken on cameras where the date hadn’t been set – so I’m back to manually editing them. Still, it’s a lot easier with a DateTimePicker control.
Source: http://www.kajabity.com/index.php/2010/01/extracting-image-properties-in-c-2/




