"He who would learn to fly one day must first learn to stand and walk and run and climb and dance; one cannot fly into flying."
-- Friedrich Nietzsche


ImageResizer is a fully managed C# imaging class designed to allow dynamic, server-side image resizing.

When added to a web project, the ImageResizer can be invoked with a single static method call that returns the path to the requested file. The object is stateless with a single public method for resizing, making it easy to integrate into any environment. Files created via the object are cached in a directory of your choice (this must be in the root or any folder in the web application). On the next request for the image, the cached version is retrieved, creating a tremendous performance benefit.

The method and properties are listed below.

Methods
Resize Returns a virtual path to the resized image.
Parameters
OutputPath (string) Virtual path to the cache folder. The ASP.NET account (or Network Service Account on Windows 2003) requires write permissions. If you wish to use the Purge method, this account requires delete permissions.
FileURL (string) Virtual path to the file to be resized (the master image).
Width (int) Desired width for the image. Ignored if the Aspect Ratio is set to Height.
Height (int) Desired height for the image. Ignored if the Aspect Ratio is set to Width.
Quality (int) 1 - 100, 1 is the lowest, 100 is the highest.
Aspect Ratio (enum) See enum definition. Defines how the image is resized.
ShadowDirectories (bool) (optional) Flag indicating whether or not the new images should be placed in a like folder structure in the image cache folder. For example, if true, "/images/family/photo.jpg" would be placed in "/cachefolder/images/family/photo.jpg/[id].jpg". If false, all images are placed in the "/cachefolder." While this shortens the path slightly, management is a bit more difficult.
AntiLeechKey (string) (optional) Acts as a salt value to the file name. By default this is not used. When a string is passed in, the salt value changes the cached filename slightly. Every time this key is changed, the output filename is changed, too. This is a simple way to help prevent bandwidth leeching by routinely (either programmatically or manually) purging the cache and setting the key to a new value. Links within the application will never break, but external links will.

PurgeCache Deletes all cached files from the cache directory.
Parameters
OutputPath (string) Virtual path to the cache folder. Requires delete permissions.

Enumerations
AspectRatio Determines how the Resize method calculates the new height and width, and, if applicable, which areas to crop.
Values
Exact Resizes the image to the specified Width and Height. May stretch image.
Width Resizes the image to the specified Width. Height parameter is ignored; the height is computed based on the width:height ratio.
Height Resizes the image to the specified Height. Width parameter is ignored; the width is computed based on the width:height ratio.
CropWidthLeft Resizes images to the specified Height and Width. Height is scaled to new dimensions. To prevent stretching, the image is anchored to the left and the width is trimmed as necessary from the right side of the image.
CropWidthCenter Resizes images to the specified Height and Width. Height is scaled to new dimensions. To prevent stretching, the image is anchored in the center. The image is trimmed equally from the left and right.
CropWidthRight Resizes images to the specified Height and Width. Height is scaled to new dimensions. To prevent stretching, the image is anchored to the right and the width is trimmed as necessary from the left side of the image.
CropHeightTop Resizes images to the specified Height and Width. Width is scaled to new dimensions. To prevent stretching, the image is anchored to the top and the height is trimmed as necessary from the bottom of the image.
CropHeightCenter Resizes images to the specified Height and Width. Width is scaled to new dimensions. To prevent stretching, the image is anchored to the center and the height is trimmed equally from the top and bottom.
CropHeightBottom Resizes images to the specified Height and Width. Height is scaled to new dimensions. To prevent stretching, the image is anchored to the bottom and the height is trimmed as necessary from the top of the image.

Developer Features

The Resize method has a number of overloads to allow for greater flexibility using the optional parameters above. In general, the ShadowDirectories boolean should be true (default). This will make content management easier. However, when shadowing the directory structure, this will add about 25 characters or so to the image path. Normally, this presents no issue as the maximum path on most Windows boxes are 255 characters. Should this present an issue, simply flip this flag to false and all images will be placed in the root cache folder. Because of the uniqueness of the filenames, this is completely acceptable.

The AntiLeech key may be useful as a simple way to help prevent bandwidth leeching. An HttpHandler is fairly simple to write that could prevent leeching by examining each incoming request, but this may not be technically possible depending on your setup, has some performance implications, and relies on checking the Http_Referrer (which may legitimately not be there). By using an AntiLeech key, the resized filenames are sufficiently changed such that bandwidth leeching is very difficult. For more information, please read this blog post.

One way to implement this is to add a key to the web.config, such as:

<appSettings>
    <add key="AntiLeech" value="mykey1" />
</appSettings>

This value can be read from the application via the following call:

System.Configuration.ConfigurationSettings.AppSettings["AntiLeech"].ToString();

As soon as this key is changed, the web application will restart and begin caching new files. The old files can be immediately purged.

This can be implemented partially for only a few images, or for the entire site. Using this site as an example, images in my art gallery use a time stamp key each time the application is restarted, but not for photos -- the artwork has proven to be a target of bandwidth leeching. Due to the fact there's only a handful of images in the Art section of my website, I could call the PurgeCache method in the Application_Start method in the Global.asax file, then, instead of using a key in the web.config, generate a new key and store it in an Application level variable. The key could be anything -- for example, the day of the year, or simply calling: DateTime.Now.ToShortDateString(); In this case, the file names change every time the application is restarted.

For this scenario, the Application_Start in the Global.asax file may look like:

protected void Application_Start(Object sender, EventArgs e)
{
        try
            {
                string PurgeFolder = Hitney.Globals.ResizeCacheDirAntiLeechFolder;
                Hitney.Imaging.ImageResizer.PurgeCache(PurgeFolder);
            }
            catch
            {
        #if DEBUG
                throw;
        #endif
            }
            Application["AntiLeechKey"] = DateTime.Now.ToString("MMddyyyyHH");
}

The exact implementation is up to you based on volume and individual need.

Downloads
Download C# Source (3k)
Download C# Source and Sample Files (152k)