System.Drawing.Image PerformanceAs I mentioned earlier, I wrote an application called
JPEG Hammer for manipulating and viewing EXIF data in digital photos. As a .NET Application the single biggest performance bottleneck has been:
Image photo = Image.FromFile(fileName, true);For a 6.1 megapixel (3008 x 2000) 1.47 MB JPEG it took on the order of
631milliseconds to load. Multiply this by 50 or so photos and you are
talking about 32 seconds to fully load these pictures. Then add the
time necessary to draw the UI for the app, update thumbnails etc. On a
1.8 ghz Pentium 4 I'd expect more... and lets just say it's no where
near as fast as the XP Shell (or other non .NET phot apps), so what
gives?
Well, after much Googling (with no success) I tried
http://support.microsoft.com/ and I came across this gem (Microsoft KB 831419):
FIX: Slow performance when you call System.Drawing.Image.FromStream to load a bitmap imageSo, curious as I am, I get my hands on this hotfix which updates:
- System.Windows.Forms.dll
- System.Design.dll
- System.Drawing.dll
Specifically, this update adds a new method to System.Drawing.Imaging:
System.Drawing.Image.FromStream(Stream stream, bool useICM, bool validateImageData)This is essentially a new signature for an existing method:
System.Drawing.Image.FromStream(Stream stream, bool useICM)As you can see,
validateImageData is a new parameter. Setting it to true is the default behavior that we have today (essentially the same as calling
FromStream(Stream stream, bool useICM)).
So I made a change to my application. Before my code looked like this:
using (Image photo = Image.FromFile(this.fileInfo.FullName, true))
{
//do stuff
}So I changed it to:
using (FileStream fs = new FileStream(this.fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite))
{
using (Image photo = Image.FromStream(fs, true, false))
{
// do stuff
}
}And here are the results. The average time it took to process 37
JPEGs taken from the same camera and roughly the same size went from
631ms to
6.76ms. So, this new method is
93x faster.
Holy Cow!!! I thought that maybe something was wrong, so I re-ran the
tests many times, and always got the same result. Simply mind boggling.
This probably brings the .NET implementation to the same speed as
writing native C code against GDI .
The good news is that the article mentions that this fix will get
rolled into the next Service Pack. However, you'll need to modify your
code as I did to take advantage of this.