I like to view photo images (.jpg files) using Large or Extra Large Icons view in Windows Explorer.  Unfortunately, this view doesn’t give me a way to sort the files by DateTaken property…  So, as a workaround, I created a small application that uses the date/time as a file name prefix, thus, letting the Windows display it in the sorted order just like I prefer…

 

I’m including the source and the compiled binary as a zipped attachment.  However, since it was written on VS 2010 Beta referencing .NET 4.0 framework, I’m also including the source code listing below, so you can copy & paste into your own project and target other versions of the framework…  Also, while I’m using WPF, you can easily change the source to using Windows.Forms instead…

 

Enjoy!

 

public static class ExtensionMethods

{

    private static Action EmptyDelegate = delegate() { };

 

    public static void Refresh(this UIElement uiElement)

    {

        uiElement.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, EmptyDelegate);

    }

}

 

 

using System;

using System.Text;

using System.Windows;

 

namespace PhotoFileRenamer

{

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

        private void BrowseFolder_Click(object sender, RoutedEventArgs e)

        {

            System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)

            {

                RootFolder.Text = dlg.SelectedPath;

 

            }

        }

 

        private void RenameFiles_Click(object sender, RoutedEventArgs e)

        {           

            StringBuilder errors = new StringBuilder();

 

            const int DateTakenPropId = 0x0132;

 

            Status.Content = "Getting file info...";

            Status.Refresh();

           

            // TODO: Add other extensions you want here...

            string[] extensions = new string[] { "*.jpg", "*.png" };

            foreach (string ext in extensions)

            {

                string[] files = System.IO.Directory.GetFiles(RootFolder.Text, ext,

                    (bool) IncludeSubfolders.IsChecked ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly);

 

                int n1 = 0, n2 = files.Length;

                foreach (string file in files)

                {

                    Status.Content = string.Format("Processing extension {0}.  File {1} of {2}...", ext, ++n1, n2);

                    Status.Refresh();

 

                    System.IO.FileInfo fi = new System.IO.FileInfo(file);

                    string fileName = fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length);

 

                    // Ignore Backup folders

                    if (fi.DirectoryName.EndsWith("\\Backup") == false)

                    {

                        string backupFolder = (bool)CreateBackup.IsChecked ? string.Format("{0}\\Backup", fi.DirectoryName) : null;

 

                        string dateTaken = "";

 

                        using (System.Drawing.Image img = System.Drawing.Image.FromFile(file))

                        {

                            // If DateTaken property not available, take the earliest of Created or Modified

                            try

                            {

                                byte[] dt = img.GetPropertyItem(DateTakenPropId).Value;

                                dateTaken = System.Text.Encoding.Default.GetString(dt);

                               

                                // The last character may be NULL => remove it

                                if (dateTaken.Substring(dateTaken.Length - 1)[0] == '\0')

                                    dateTaken = dateTaken.Substring(0, dateTaken.Length - 1);

 

                                dateTaken = dateTaken.Replace(":", "-");

                            }

                            catch

                            {

                                DateTime dt = fi.CreationTime < fi.LastWriteTime ? fi.CreationTime : fi.LastWriteTime;

                                dateTaken = dt.ToString("yyyy-mm-dd HH-MM-ss");

                            }

                        }

                       

 

                        if (fileName.StartsWith(dateTaken) == false)

                        {

                            string newFile = string.Format("{0}\\{1} {2}", fi.DirectoryName, dateTaken, fi.Name);

                            string backupFile = string.IsNullOrEmpty(backupFolder) == false ? string.Format("{0}\\{1}", backupFolder, fi.Name) : null;

                            try

                            {

                                if (string.IsNullOrEmpty(backupFile) == false)

                                {

                                    if (System.IO.Directory.Exists(backupFolder) == false)

                                        System.IO.Directory.CreateDirectory(backupFolder);

 

                                    fi.CopyTo(backupFile, true);

                                }

 

                                fi.MoveTo(newFile);

                            }

                            catch (Exception ex)

                            {

                                errors.AppendLine(string.Format("{0} - {1}", file, ex.Message));

                            }

                        }   // startsWith(dateTaken)

                    }   // ignore Backup folder

                }   // foreach file

            }   // foreach extension

 

            if (errors.Length > 0)

                Status.Content = string.Format("Done with errors: \r\n\r\n{0}", errors.ToString());

            else

                Status.Content = "Done!";

 

        } // method end

       

    }

}