Image Transforms with the ASP.NET Generated Image Control
By Scott Mitchell
Introduction
Last week's article - Dynamically Generating and Caching Images in ASP.NET with the GeneratedImage Control - looked at how to programmatically create and cache images on the fly using the GeneratedImage control, one of a suite of "Futures" technologies found in the ASP.NET Team's CodePlex site. Programmatically creating and displaying images entails the use of an HTTP Handler for generating the binary content of the dynamically-generated image. While this HTTP Handler can be implemented as an ASP.NET page, the GeneratedImage control includes the
ImageHandler
class, which serves as a base class for HTTP Handlers designed specifically to generate and serve dynamic images and includes built-in functionality for caching images on the
client and/or web server. Last week's article illustrated both how to create an HTTP Handler for generating dynamic images (one that extended ImageHandler
) as
well as how to use the GeneratedImage Web control to display such dynamically-generated images in a web page.
In addition to its image generation and caching features, the ImageHandler
class includes functionality for performing image transforms. An image
transformation is a process that takes an image as input, modifies it in some way, and outputs the modified image. Common image transformations include image resizing,
changing the image's color information (such as transforming a color image into a black and white one), and adding a watermark to the image. What's more, transformations can
be chained together. For example, you could take an original image and feed in into the resize transformation. The output of the resize transformation could then be used as
the input of the watermark transformation, which would then output the resized image with a watermark.
The GeneratedImage control ships with an image transform class that resizes the original image, as well as an ImageTransform
class that serves as a base class
for creating your own image transform classes. This article illustrates how to use resize dynamically-created images on the fly as well as how to create your own image transform
classes. Read on to learn more!
Applying Image Transforms
The
ImageHandler
class, which serves as a base class for the HTTP Handler classes used to dynamically generate images using the GeneratedImage control,
includes a property named ImageTransforms
that specifies what image transforms (and in what order) are applied to the generated image. Specifically, the
ImageTransforms
property holds a collection of objects that derive from the ImageTransform
class. The ImageTransform
class is another
class in the GeneratedImage API that serves as a base class for classes that can perform image transforms. The API includes a class named ImageResizeTransform
, which
extends ImageTransform
. (We'll look at using the ImageResizeTransform
shortly, and later we'll see how you can create your own custom image transform
classes).
To apply an image transform to a dynamically-generated image, simply add an instance of the image transform class to the ImageTransforms
property in either the
HTTP Handler's constructor or in the GenerateImage
method. For instance, the following HTTP Handler snippet applies two image transform classes to the image generated
by the HTTP Handler.
Public Class ApplyImageTransformsHandler
|
As you can see from the code above, you can apply any number of image transform classes to the ImageHandler
class's ImageTransforms
property.
If the image transform class does not require that you set any property values, you can instantiate the image transform class directly in the call to the
ImageTransforms
property's Add
method, as in MyBase.ImageTransforms.Add(New SomeImageTransformClass)
. More likely, you'll need
to first set a variety of properties of the image transform class. In that case, start by creating an instance of the image transform class, set its properties, and then add
the instance to the ImageTransforms
collection.
Keep in mind that the specified image transforms are applied after the image is generated by the GenerateImage
method. Furthermore, the transforms are applied
in the order in which they appear in the ImageTransforms
list. In other words, with the above example the GenerateImage
method is responsible for
creating the original image. Next, the SomeImageTransformClass
image transform class is applied to the original image. It's output is then fed as input into
the SomeOtherImageTransformClass
image transform class and that output is what is returned to the client.
Resizing Images With The ImageResizeTransform
Class
The GeneratedImage API ships with a built-in image transform class,
ImageResizeTransform
.
As its name implies, ImageResizeTransform
resizes the original
image to an alternate size. This is particularly useful in websites where there are commonly very large, high-resolution pictures that need to sometimes be shown in a smaller,
more compact view.
Consider a website like Flickr, which allows visitors to upload their digital pictures. Typically, digital pictures are very large, both in terms
of file size and dimensions. For example, a digital picture might be more than 2,000 pixels wide by 1,000 pixels tall and consume upwards of 1 MB of disk space. Clearly, displaying
such images on your website will not only stretch out your pages, but also greatly impact the total bandwidth used by the site. When you sign on to Flickr you see your
picture library as a series of resized images that do not exceed 240 pixels in width, thereby permitting multiple columns of pictures to be listed on a single page.
While the ASP.NET Image web control has Width
and Height
properties that let you specify the dimensions of the image on the browser, these properties
do not actually resize the image. Instead, the web server still transmits the entire contents of the original image, which the browser then scales to the specified width and height.
In order to reduce both the dimensions and the file size, you need to resize the image.
If you have a predetermined, known quantity of high-resolution images, you can proactively create smaller versions of these images using an image editing program like Photoshop.
But if your site has user-added pictures or dynamically-generated images, and you need to resize these source images into smaller versions, then you'll need to resize the image
dynamically. This is where the ImageResizeTransform
class can help.
The following code snippet shows an HTTP Handler that extends the ImageHandler
class and uses the ImageResizeTransform
class to resize an image file
to a width of 200 pixels. (The resized image's height is automatically scaled to the appropriate height.) Specifically, this code resizes an image file that resides on the
web server's file system (note that the URL to the image to resize is specified via the parameters
collection), although the resize transform could be applied
to a dynamically-generated image.
Public Class ResizeImageHandler
|
In the HTTP Handler's constructor an instance of the ImageResizeTransform
class is created and its Width
property is set to 200, which resizes
the resulting image to 200 pixels with the height auto-scaled. The GenerateImage
method reads in the ImageUrl
parameter, which contains the
path to the image to resize. This parameter contains the virtual path to the image, such as ~/Images/Picture.jpg
. In order to load the image we need to know
the physical path, such as C:\MyWebsite\Images\Picture.jpg
. This translation from virtual to physical paths is performed by the Server.MapPath
method and saved in the imageFile
variable. Next, a check is performed to ensure that the file exists; if it does not, an ArgumentException
is
thrown. However, if the image exists then its bytes are read via the File.ReadAllBytes
method and passed into the constructor for a new ImageInfo
object, which is what the GenerateImage
method must return.
After the GenerateImage
method completes, the ImageHandler
applies the ImageResizeTransform
transform, which resizes the specified
image to have a width of 200 pixels. This resized image is what is returned to the requesting client.
The download available at the end of this article includes a more refined resizing HTTP Handler, one where the width or height of the resized image can also be specified
via the parameters
collection. This HTTP Handler can be found in the demo at ~/ImageHandlers/ResizeImageHandler.ashx
; there's also a web page named
~/Demos/TransformDemo.aspx
that contains a GeneratedImage Web control with the following declarative markup:
<cc1:GeneratedImage ID="ResizedImageGenerator" runat="server" ImageHandlerUrl="~/ImageHandlers/ResizeImageHandler.ashx">
|
The original image, Hiking.jpg
, an original resolution of 2589 x 1249 and over 940 KB in size and resizing it to 400 x 193 pixels with a total file size of
32 KB. To see this resizing in action, download the demo or check out the
original picture and compare it with the resized one below.

Creating a Custom Image Transform Class
The
ImageResizeTransform
class derives from the ImageTransform
class, which spells out the base functionality of a class that performs image transforms.
Specifically, the ImageTransform
class includes an abstract method (one that must be overridden) named ProcessImage
, which is responsible for performing
the transform. The ProcessImage
method is passed an Image
object as input and returns the transformed image as its output (also as an
Image
object).
It is possible to create your own image transform classes and to use them in your HTTP Handlers. The demo available for download at the end of this article includes a custom
image transform class named ImageWatermarkTransform
. As its name implies, ImageWatermarkTransform
transforms the input image by adding a watermark.
This image transform class contains properties like WatermarkText
, FontColor
, FontFamily
, and other properties that affect the
display and rendering of the watermark. In the ProcessImage
method it takes the input image and adds the watermark, locating it in the center of the image.
The following code snippet shows the germane parts of the ImageWatermarkTransform
class, namely the ProcessImage
method. This method starts by creating
a Font
object based on the values of the class's FontFamily
and FontSize
properties. Next, a Graphics
object is created to work on the
input image (image
). The size of the watermark is measured; next, the coordinates to place the watermark and the center of the image are computed. Finally, the
watermark is added to the image via the DrawString
method, and the modified image is returned.
Public Class ImageWatermarkTransform
|
In addition to creating this image transform class, I also created an HTTP Handler named WatermarkAndResizeImageHandler.ashx
that uses both the ImageWatermarkTransform
and ImageResizeTransform
transform classes to first (optionally) resize an image and then to (optionally) add a watermark. The code is quite similar to that of the
ResizeImageHandler.ashx
HTTP Handler, which we examined earlier in this article. The only difference is the addition of the ImageWatermarkTransform
class,
which is highlighted in the snippet below.
Public Class WatermarkAndResizeImageHandler
|
The WatermarkDemo.aspx
page uses the GeneratedImage Web control to display the Hiking.jpg
photo resized to 350 pixels wide (and auto-scaled to
168 pixels tall) with the watermark "Copyright Scott Mitchell" prominently displayed using a yellow, Comic Sans MS font of size 18pt.

Keep in mind that the image transforms are applied in the order they appear in the ImageTransforms
list. In the above example, the image is first resized
and then a watermark is added. However, if you reversed the order with which the image transform classes are added to the ImageTransforms
property then the image
would first have a watermark added and then be resized.
Conclusion
The ASP.NET GeneratedImage control makes it easy to work with dynamically-generated images. This article (and last week's article) showed how to use this control and the classes that make up its API to serve dynamic images, cache them, and apply image transforms. The GeneratedImage control ships with one built-in image transform class,
ImageResizeTransform
. You can also create your own custom image transform classes, as this article illustrated.
Happy Programming!
Attachments: