Add EXIF date to photo

If you have a photo that you need to add a timestamp to the EXIF information, you can use the following .NET code. Apparently there are a ridiculous number of formats and standards which are incompatible with each other and conflicting, but from what I’ve found, this should cover regular use cases.

I’m sure there’s a better solution, but this requires that you have some unrelated image file that has the appropriate tags in it, in case your photo is missing the properties entirely. Not exactly a great solution, but it does seem to work.

static void Go(string oldFile, string newFile) {
    DateTime theDate = new DateTime(2009, 1, 15);

    Func<int, PropertyItem> getPropItem = id => {
        using (var image = Image.FromFile(@"c:\temp\IMG_6139.jpg")) { // Some unrelated image file that already has EXIF data
            return image.GetPropertyItem(id);
        }
    };

    using (var image = Image.FromFile(oldFile)) {
        PropertyItem propItem;
        int ID = 0x9004;
        try {
            propItem = image.GetPropertyItem(ID);
        } catch {
            propItem = getPropItem();
        }
        propItem.Value = Encoding.UTF8.GetBytes(theDate.ToString("yyyy\\:MM\\:dd HH\\:mm\\:ss") + "\0");
        image.SetPropertyItem(propItem);

        ID = 0x0132;
        try {
            propItem = image.GetPropertyItem(ID);
        } catch {
            propItem = getPropItem();
        }
        propItem.Value = Encoding.UTF8.GetBytes(theDate.ToString("yyyy\\:MM\\:dd HH\\:mm\\:ss") + "\0");
        image.SetPropertyItem(propItem);

        image.Save(newFile, ImageFormat.Jpeg);
    }
}

Get EXIF date from photo

It’s not straightforward to retrieve the EXIF date from an image. Here’s a method to retrieve it using the MetadataExtractor package. It looks for the appropriate date, and if not found, falls back to the file properties.

// <package id="MetadataExtractor" version="2.0.0" targetFramework="net40" />

static DateTime GetImageDate(string file) {
    var directories = ImageMetadataReader.ReadMetadata(file);
    ExifSubIfdDirectory subIfdDirectory = null;
    try { 
        subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
    } catch (Exception ex) {
    }
    DateTime? dateTime;
    try {
        dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTime);
        return dateTime.Value;
    } catch (Exception ex) {
        try {
            dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal);
            return dateTime.Value;
        } catch (Exception ex1) {
            try {
                dateTime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeDigitized);
                return dateTime.Value;
            } catch (Exception ex2) {
                dateTime = new[] {
                    System.IO.File.GetCreationTime(file),
                    System.IO.File.GetLastWriteTime(file)
                }.Min();
                return dateTime.Value;
            }
        }
    }
}

Add EXIF date to photo

Description

If you have a photo that you need to add a timestamp to the EXIF information, you can use the following .NET code. Apparently there are a ridiculous number of formats and standards which are incompatible with each other and conflicting, but from what I’ve found, this should cover regular use cases.

I’m sure there’s a better solution, but this requires that you have some unrelated image file that has the appropriate tags in it, in case your photo is missing the properties entirely. Not exactly a great solution, but it does seem to work.

static void Go(string oldFile, string newFile) {
    DateTime theDate = new DateTime(2009, 1, 15);

    Func<int, PropertyItem> getPropItem = id => {
        using (var image = Image.FromFile(@"c:\temp\IMG_6139.jpg")) { // Some unrelated image file that already has EXIF data
            return image.GetPropertyItem(id);
        }
    };

    using (var image = Image.FromFile(oldFile)) {
        PropertyItem propItem;
        int ID = 0x9004;
        try {
            propItem = image.GetPropertyItem(ID);
        } catch {
            propItem = getPropItem();
        }
        propItem.Value = Encoding.UTF8.GetBytes(theDate.ToString("yyyy\\:MM\\:dd HH\\:mm\\:ss") + "\0");
        image.SetPropertyItem(propItem);

        ID = 0x0132;
        try {
            propItem = image.GetPropertyItem(ID);
        } catch {
            propItem = getPropItem();
        }
        propItem.Value = Encoding.UTF8.GetBytes(theDate.ToString("yyyy\\:MM\\:dd HH\\:mm\\:ss") + "\0");
        image.SetPropertyItem(propItem);

        image.Save(newFile, ImageFormat.Jpeg);
    }
}