I have developed a simple little program for setting the date and time stamps on JPG images. The program will change the “DateTime,” “DateTimeOriginal,” and the “DateTimeDigitized” EXIF properties/tags and once it writes out the new file, it changes the filesystem create, modify, and last access timestamps to be the specified time. Unfortunately a loss of quality is felt here because the file is re-compressed lossily. The program is written in C# using the .net framework but I’m fairly confident it will work with mono.
You would be pretty surprised how much extra complication a progress bar adds to a GUI application assuming you add it properly and allow the GUI to remain responsive during processing. In order to accomplish that you must spawn off a separate thread so that the GUI controls and the work of processing the images are separate execution units. In the worker thread you must update the progress bar, but for some reason Windows (and/or the .net framework) enforces upon you that a thread cannot directly access an object created in a different thread; at least for GUI form controls. Why this is so I am unsure, maybe it has something to do with the lower level system calls that get performed to draw the windows form controls using GDI+; but who knows.
To get around this limitation you have to create a delegate function which calls another function to actually manipulate the progress bar. Once you have the delegate you have to instantiate an instance of the delegate and pass that to the BeginInvoke function, which is probably some .net special “system call.” Only using the BeginInvoke function on the object you want to manipulate, or the form instance, with the delegate can you perform cross-thread manipulation of form controls. I find this utterly retarded coming from a multithreading background of using C and the pthreads library on linux; where you can access anything in the processes memory space regardless which thread it was “created” in.
I have done the delegate creation thing the hard way and just recently the easy way with lambda functions so all I have to do to manipulate the progress bar in the worker thread is as follows:
this.BeginInvoke((Action)(() => progressBar1.Value = 0));
I find this fairly slick.
Anyway, have fun looking at the code. I put it up on github because I’d never used it before and it looks easy as fuck to use. Plus git is the shit.
Feel free to use the Contact me link in the bottom right of the site to send me feedback on the program.