A Simple Resizing API
While the code above will produce good quality thumbnails of arbitrary dimensions, this isn't always what you want. In fact, most of the time, you'll want to keep the image's aspect ratio the same, and resize it proportionally so that either the final image has a specified pixel width or height, or it has been scaled down to a specified percentage of its original dimensions. For convenience, I decided to put all this together into a dedicated assembly, which exposes the following simple API:
Table 2. API for the ImageResize class
| Name
|
Class
|
Type
|
Description
|
| File
|
Property
|
String
|
Sets the path from which the image should be loaded
|
| Image
|
Property
|
Image
|
Sets the image object from which to generate thumbnails
|
| PreserveAspectRatio
|
Property
|
Bool
|
Flag denoting whether the aspect ratio of the original image should be preserved (default is true)
|
| UsePercentages
|
Property
|
Bool
|
Whether to interpret the Width and Height properties as absolute dimensions or percentages of the original image dimensions
|
| Width
|
Property
|
Double
|
The width of the thumbnail
|
| Height
|
Property
|
Double
|
The height of the thumbnail (units depend on whether UsePercentages is true or false)
|
| GetThumbnail
|
Method
|
Image
|
Creates a thumbnail based on the properties that have been specified
|
I could just as soon have exposed a single, static method, but I find a formal
ImageResize object both more intuitive and more flexible for several reasons. First, if you want a thumbnail of a specified height but don't care about the width, you just set the
ImageResize object's
Height property and don't specify a
Width. In contrast, if I'd implemented
GetThumbnail as a fully parameterized method, you would have had to pass in some "magic number" (perhaps 0 or –1) to signify that you didn't want to specify this field.
Second, resizing large images takes a lot of processing power and uses a lot of RAM, as I discovered while experimenting with the raw JPEGs downloaded from my digital camera. With an object-based approach you can cache images for immediate performance benefits. For example, the first thing
GetThumbnail does is to check whether the source image has changed; if not, it uses the last image it has available. This means that if you need to generate thumbnails repetitively from a single image (for example, by displaying the image in a window and letting the user drag it to a new size with the mouse), the loading step only happens once. By the same token, if none of the
ImageResize object's properties have changed between consecutive calls to
GetThumbnail, it returns you a cached image rather than calculating a new one.
Finally, the object-based approach lets you group your preferred settings in one place, which makes for simpler code when you want to perform the same operation on a lot of different images.
To use the class, just compile the ImageResize assembly and add a reference to it in any projects that need to resize images. For example, the following code loads an image called "tabi.jpg," and reduces it to 35 percent of its original size, while maintaining its aspect ratio:
ImageResize o = new ImageResize();
o.File = "c:/temp/tabi.jpg";
o.Height = 35;
o.UsePercentages = true;
o.GetThumbnail().Save("c:/temp/test.jpg",
System.Drawing.Imaging.ImageFormat.Jpeg);
If instead I'd wanted to resize the image to absolute percentage or pixel dimensions, I would have specified a Width as well as a Height for my resized image.
Images for the Web
When I originally wrote the ImageResize class I envisaged I would mostly be using it from Windows Forms-based applications. However, it's just as easy to use it server-side in order to stream dynamically resized images on demand. All you need to do is set the content type to "image/jpeg" and stream the image directly into the Response stream in your
Page_Load() method:
Response.ContentType = "image/jpeg";
ImageResize o = new ImageResize();
// Load your image and perform any resizing here
o.File = …
o.GetThumbnail().Save(Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Jpeg);
Hopefully this simple class will cover most of your image resizing needs, as well as take care of basic image caching issues, leaving you free to concentrate on the more important programming tasks. It should also keep you from scratching your head when
GetThumbnailImage doesn't return the data you expect.