ASP.NET and the .NET framework make the task of generating images on the fly very easy. With classic ASP, developers were forced to use third-party components like ASPImage and ASPPicture for dynamic image manipulation. Fortunately, with ASP.NET, those days are over. Various image manipulation capabilities are now built directly into the .NET framework classes.
The .NET Framework offers several classes for image generation and manipulation. ASP.NET developers can use these classes to draw various shapes, create text, and generate images in many different formats, including GIF, JPEG, PNG, etc.
Now, for the inevitable question: why would you need to generate images on the fly for your ASP.NET Web pages? Here are several practical applications of dynamic image generation:
- Generate a thumbnail gallery from your full-size gallery images.
- Create dynamic charts based on dynamic user input or database data.
- Generate images with random text (access code) for use with your user registration pages to prevent automated registrations.
Create a Text Image on the Fly
Let's use two .NET classes located in the System.Drawing namespace to illustrate how to create images on the fly with ASP.NET. The two framework classes are System.Drawing.Bitmap and System.Drawing.Graphics.
To demonstrate simple dynamic ASP.NET image generation, we'll create an ASP.NET Web page with two dropdown boxes, one text box, and a button. The first dropdown box allows us to choose the background color of our image, while the second allows us to select a font. The text box will receive the text that will be displayed on the image, and the button will generate the image. Here's the code that displays these form elements:
<form runat="server">
<asp:TextBox runat="server" id="Text" />
<asp:dropdownlist runat="server" id="BackgroundColor">
<asp:ListItem Value="red">Red</asp:ListItem>
<asp:ListItem Value="green">Green</asp:ListItem>
<asp:ListItem Value="navy">Navy</asp:ListItem>
<asp:ListItem Value="orange">Orange</asp:ListItem>
</asp:dropdownlist>
<asp:dropdownlist runat="server" id="Font">
<asp:ListItem Value="Arial">Arial</asp:ListItem>
<asp:ListItem Value="Verdana">Verdana</asp:ListItem>
<asp:ListItem Value="Courier">Courier</asp:ListItem>
<asp:ListItem Value="Times New Roman">Times New Roman</asp:ListItem>
</asp:dropdownlist>
<asp:Button runat="Server" id="SubmitButton" Text="Generate Image" />
</form>
Every time you request an ASP.NET page, the Page_Load event is triggered on the server and the Page_Load sub-routine is called. Within this sub-routine, you can check to see whether the request for the page was generated via a data postback (the user clicked on the submit button, for example), whether the user came to this page from another page, or whether the user simply typed the page URL into the browser's address bar.
In this example, it's important to know if the page was posted back or not, because we want to generate a dynamic image only when the user clicks on the submit button -- not when he of she first loads the page. The Page.IsPostBack property is true if the APS.NET page is loaded in response to a client postback; otherwise, it's false. So the first thing we do within the Page_Load sub-routine is check the value of Page.IsPostBack:
If Page.IsPostBack Then
If the value is false, we don't do anything and the page merely displays the ASP.NET controls we declared above. If the value is true, we must generate an image. Here's how it's done.
The first step in creating our dynamically generated image is to create a new Bitmap object, and to specify the width and the height of the image we're generating:
Dim oBitmap As Bitmap = New Bitmap(468, 60)
The next step is to create a new Graphics object, which will allow us to draw on our bitmap:
Dim oGraphic As Graphics = Graphics.FromImage(oBitmap)
We then declare a structure of type System.Drawing.Color (represents an RGB color), which will define the background color of our dynamic image:
Dim oColor As System.Drawing.Color
Now, we need to get the values that were posted back to the page from the two dropdown boxes and the text box:
Dim sColor As String = Request("BackgroundColor")
Dim sText As String = Request("Text")
Dim sFont As String = Request("Font")
We run a Select Case statement to set the value of oColor (the background color of our image), depending on the sColor value:
Select Case sColor
Case "red"
oColor = Color.Red
Case "green"
oColor = Color.Green
Case "navy"
oColor = Color.Navy
Case "orange"
oColor = Color.Orange
Case Else
oColor = Color.Gray
End Select
Next, we create two brushes, which will help us to draw our image. The first one, oBrush, will be used to draw the background of the image:
Dim oBrush As New SolidBrush(oColor)
The second brush will be used to draw the text entered by the user; we hardcode the brush color as white:
Dim oBrushWrite As New SolidBrush(Color.White)
We're going to use the first brush to fill the image rectangle, because the default color of new bitmaps is black. We call the FillRectangle method of oGraphic to paint the background in the color selected by the user (oColor):
oGraphic.FillRectangle(oBrush, 0, 0, 468, 60)
So far, we've changed the background color of our image, but we haven't written any text. We'll use the DrawString method of the oGraphic object to do that. The DrawString method has several overloads. This is the one we're going to use:
DrawString(String, Font, Brush, FPoint)
The first parameter is just the string that we want to write; the second parameter defines the font to be used; the third parameter defines a brush (this will be the second brush we created above); the last parameter defines a drawing starting point relative to the top-left corner of our image. Before we call the DrawString method, however, we need to create an instance of the Font class, and FPoint structure that defines the point at which drawing should start.
The user chose a font for the text, so we pass sFont as the first parameter, and hardcode the second parameter, which defines the font size:
Dim oFont As New Font(sFont, 13)
Then, we define a structure of type PointF, which represents an ordered pair of X and Y coordinates that define a point in a two-dimensional plane. Again, we just hardcode the drawing start point for the text, because this is not configurable in our example:
Dim oPoint As New PointF(5F, 5F)
We can now call the DrawString method and draw our text:
oGraphic.DrawString(sText, oFont, oBrushWrite, oPoint)
The last thing that's left to do is to save the newly created image on the server:
oBitmap.Save(Server.MapPath("generated_image.jpg"), ImageFormat.Jpeg)
This code saves the image in JPEG format, but you can save it as GIF, TIFF, PNG, or any other popular image format.
Finally, we display a link to our new image:
Response.Write("View the generated image <a target=""_blank"" href=""generated_image.jpg"">here</a>")
If you don't want to save the image on the server file system, you can send it directly to the browser using the following code:
Response.ContentType = "image/jpeg"
oBitmap.Save (Response.OutputStream, ImageFormat.Jpeg)
In fact, you can house the code that generates the dynamic image in a separate ASP.NET page, and reference this page from other ASP.NET pages like this:
<img src="image_generate.aspx">
Of course, your image_generate.aspx page has to have the proper image ContentType, for example:
Response.ContentType = "image/jpeg"
Or:
Response.ContentType = "image/gif"
You can find the full source code of this page at the end of this article.
Create a Thumbnail on the Fly
Let's now look at images as we step through the process involved in dynamically creating thumbnails in ASP.NET.
First, we'll create an ASP.NET page called thumbnail.aspx and import the System.Drawing and System.Drawing.Imaging classes:
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
The thumbnail.aspx page will get 3 parameters in its query string:
image -- the file path of the image file that will be resized to a thumbnail
w -- the desired width of the thumbnail
h -- the desired height of the thumbnail
In the Page_Load sub-routine, we declare 2 System.Drawing.Image objects -- oImage and oThumbnail. Then we get the absolute path of the image file with the following line:
sImagePath = Server.MapPath(Request.QueryString("image"))
Note: be aware of the security implications here. By passing a tricky image parameter in the query string, a hacker could persuade the script to attempt to access and display any file on the server, whether it's part of your Website or not. To guard against this, you'd want to ensure that your file system permissions were correctly configured; also, some validation logic for the parameter would not go astray in this script. For the purposes of this article, however, we'll stick with this naïve approach.
On the next step, we actually create the oImage object using the FromFile method and passing the absolute file path we got in the previous step.
oImage = oImage.FromFile(sImagePath)
Then we get the desired thumbnail width and height:
iWidth = Request.QueryString("w")
iHeight = Request.QueryString("h")
The next step is to use the GetThumbnailImage method, which gets a thumbnail image from an Image object:
oThumbnail = oImage.GetThumbnailImage(iWidth, iHeight, Nothing, Nothing)
We pass the width and the height of the thumbnail as the first two parameters. For the purpose of this article, it's enough to pass Nothing as third and fourth parameters of the GetThumbnailImage method, without any further explanation.
Finally, as in the previous example, we directly send the image to the browser using the following code:
Response.ContentType = "image/jpeg"
oThumbnail.Save (Response.OutputStream, ImageFormat.Jpeg)
It was that easy!
The fully functional VB.NET source-code of both examples can be downloaded here.
See both pages in action here:
http://someanswers.com/text_image.aspx
the original image (courtesy of freefoto.com)
http://someanswers.com/thumbnail.aspx?image=tree.jpg&w=150&h=100
http://someanswers.com/thumbnail.aspx?image=tree.jpg&w=75&h=50
http://someanswers.com/thumbnail.aspx?image=tree.jpg&w=300&h=200
|