Fast Image Loading without asking for the hot-fix or waiting for the service pack...
Omar Shahine is doing some great work on his JPEG Hammer application. He talks about finding some hot-fixes for the System.Drawing.Image class that provide overloads for disabling image verification. While this is inherently unsafe, and you now have to have elevated permissions to use the class, I figured, what the hell, why not make this readily available to everyone without the need to install a hot-fix. System.Drawing.Image Performance.
Note my method isn't any better than the hot-fix. It does require private reflection permissions. The reason for this is the absurd protection of the Image and Bitmap classes in System.Drawing. I start by doing a simple Gdip load on the stream, then I use private reflection to instantiate a Bitmap over my loaded file. This prevents the GdipImageForceValidation function from being called, and does all of the necessary internal fix-ups of the native image pointers inside of the Image class. Note the method, EnsureSave, is not being called, so animated gifs might not load properly using this method. Also, only bitmapped types will be loaded. I could add additional logic to also load metafiles, but I don't see the point. Enjoy!
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
public class ImageFast {
[DllImport("gdiplus.dll", CharSet=CharSet.Unicode)]
public static extern int GdipLoadImageFromFile(string filename, out IntPtr image);
private ImageFast() {
}
private static Type imageType = typeof(System.Drawing.Bitmap);
public static Image FastFromFile(string filename) {
filename = Path.GetFullPath(filename);
IntPtr loadingImage = IntPtr.Zero;
// We are not using ICM at all, fudge that, this should be FAAAAAST!
if ( GdipLoadImageFromFile(filename, out loadingImage) != 0 ) {
throw new Exception("GDI+ threw a status error code.");
}
return (Bitmap) imageType.InvokeMember("FromGDIplus", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { loadingImage });
}
}