3

I'm a little bit surprised and puzzled. I try to read the property items from an image. Particularly, I'm interested in the "Date Taken". I have written a procedure that does exactly that. More or less. With some files it works perfectly, but...

I have some files that have a 'Date Taken' in the properties (when viewed by Windows Explorer, Windows 7 x64). They differ from the date created, modified and accessed. So I do have a 4th date. However, if I loop through the property items, it does not show up (on any ID). When I look for it on the PropertyItem.Id (0x9003 or 36867), i get that the property item does not exist.

My Code to loop through the property items:

        for (int i = 0; i < fileNames.Length; i++)
        {
            FileStream fs = new FileStream(fileNames[i], FileMode.Open, FileAccess.Read);
            Image pic = Image.FromStream(fs, false, false);



            int t = 0;
            foreach (PropertyItem pii in pic.PropertyItems)
            {
                MessageBox.Show(encoding.GetString(pii.Value, 0, pii.Len - 1) + " - ID: " + t.ToString());
                t++;
            }
        }

The code to read only the "Date Taken" property (I stole from here: http://snipplr.com/view/25074/)

    public static DateTime DateTaken(Image getImage)
    {
        int DateTakenValue = 0x9003; //36867;

        if (!getImage.PropertyIdList.Contains(DateTakenValue))
            return DateTime.Parse("01-01-2000");

        string dateTakenTag = System.Text.Encoding.ASCII.GetString(getImage.GetPropertyItem(DateTakenValue).Value);
        string[] parts = dateTakenTag.Split(':', ' ');
        int year = int.Parse(parts[0]);
        int month = int.Parse(parts[1]);
        int day = int.Parse(parts[2]);
        int hour = int.Parse(parts[3]);
        int minute = int.Parse(parts[4]);
        int second = int.Parse(parts[5]);

        return new DateTime(year, month, day, hour, minute, second);
    }

However, when I change the date taken in the 'File properties window' of Windows Explorer, It starts to show up in my program.

So my question is: Where does this "Date Taken" comes from? How can I access it? Could it be that there is another source of information besides the EFIX Data?

Thanks!

Jan Solo
  • 183
  • 1
  • 8
  • 19
  • see if the information on this page can help you http://stackoverflow.com/questions/180030/how-can-i-find-out-when-a-picture-was-actually-taken-in-c-sharp-running-on-vista | or check this link [Getting Picture Properties](http://www.kajabity.com/2010/01/extracting-image-properties-in-c-2/) – MethodMan Jan 13 '13 at 21:24

3 Answers3

13

you can try something like this if you want to start with some basic coding

// Load an image however you like. System.Drawing.Image image = new Bitmap("my-picture.jpg");

Referenced from AbbydonKrafts

// Get the Date Created property 
//System.Drawing.Imaging.PropertyItem propertyItem = image.GetPropertyItem( 0x132 );
System.Drawing.Imaging.PropertyItem propertyItem 
         = image.PropertyItems.FirstOrDefault(i => i.Id == 0x132 ); 
if( propItem != null ) 
{ 
  // Extract the property value as a String. 
  System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); 
  string text = encoding.GetString(propertyItem.Value, 0, propertyItem.Len - 1 ); 

  // Parse the date and time. 
  System.Globalization.CultureInfo provider = CultureInfo.InvariantCulture; 
  DateTime dateCreated = DateTime.ParseExact( text, "yyyy:MM:d H:m:s", provider ); 
}
MethodMan
  • 18,625
  • 6
  • 34
  • 52
  • 1
    Man, this is exactly what I've been trying to do for the last ages with qQuery and having loads of problems. Great answer, thanks (Can't believe this hasn't been upvoted and accepted) – Mikey Mouse Mar 05 '13 at 16:27
  • I am using this solution exactly and I keep running the same test over and over to check to see if this is working and about half the time the PropertyItems property on image is an empty array. Do you know why that might be? Same image being uploaded and same test being run. – GBreen12 Oct 17 '14 at 19:27
  • are you stepping thru the code..? do you know if perhaps you have null or empty values of something that is not persisting where you expect it to.. ? what event or process in your program are you running the code...? – MethodMan Oct 17 '14 at 19:30
  • Yeah I am stepping through the code and basically the process is a file upload through WebApi. It comes into my controller and I create a byte array. When it gets into the service layer I run this method where it turns it into an Image and that's where I set the breakpoint. Sometimes it will be randomly empty and sometime it will have 28 values. – GBreen12 Oct 17 '14 at 19:39
  • I have ran into this before and the way I got around it was to add that upload control inside of an update panel and setting the updatepanel's mode to conditional .. I have another way that works as well I have done a few weeks ago but my personal machine is at home.. I will try to remember to come back here on monday and post that example as well – MethodMan Oct 17 '14 at 19:41
  • This works but this line `System.Drawing.Imaging.PropertyItem propertyItem = image.GetPropertyItem( 0x132 );` throws an exception if the specified property is null. Consider replacing that line with `System.Drawing.Imaging.PropertyItem propertyItem = image.PropertyItems.FirstOrDefault(i => i.Id == 0x132 );` which returns a null instead of an exception for a null property – Moses Machua Aug 04 '15 at 01:34
1

Change the .ParseExact line to the following

DateTime dateCreated = DateTime.ParseExact( ConvertToString(dateTakenProperty)**.Substring(0, 19)**, "yyyy:MM:dd HH:mm:ss", provider )

At the end of the string there is probably a null character which can't be processed. Doing a .SubString for the expected length will fix it.

verbedr
  • 1,784
  • 1
  • 15
  • 18
1

Well, I am obtaining the "Modified" date of my image file instead of the Date Taken. I have achieved using the following code:

public static System.DateTime GetImageDate(string filePath)
  {
     System.Drawing.Image myImage = Image.FromFile(filePath);
     System.Drawing.Imaging.PropertyItem propItem = myImage.GetPropertyItem(36867);
     string dateTaken = new System.Text.RegularExpressions.Regex(":").Replace(System.Text.Encoding.UTF8.GetString(propItem.Value), "-", 2);
     return System.DateTime.Parse(dateTaken);
  }