devxlogo

Using GDI+ in ASP.NET Web Applications, Part I

Using GDI+ in ASP.NET Web Applications, Part I

DI+ is a technology that developers generally associate with Windows Forms applications because they use it to draw anything on the screen from custom controls to diagrams. However, you can also use GDI+ in ASP.NET Web applications whenever you want to serve up dynamic images. You can use GDI+ to create dynamic banners, photo albums, graphs, diagrams, and more.

GDI+ is the .NET Framework wrapper assembly for Microsoft’s GDI (Graphics Device Interface) technology. In simple terms, you use GDI+ to draw on a drawing surface such as a Window, Control (technically just a window), or Bitmap, among others. Drawing with GDI+ is rather straightforward. You just need a Graphics object that links you to a drawing surface and off you go.

GDI+ uses a Graphics object as the main means to draw on a surface. The Graphics object has methods including DrawLine() or DrawArc() to draw line-based graphics, and FillEllipse() and FillPath() to fill areas with color. If you’ve used GDI (without the “+”) in the past, this is a little different. In conventional GDI, drawing and filling happens in one step, while GDI+ separates the two tasks into individual method calls. In GDI+ you draw with Pens. A Pen is an object that exposes properties such as line color, line thickness, drawing patterns, and end-points such as arrows. You can create your own pens, but for most scenarios the .NET Framework provides all the pens you will ever need. If you want to fill an area, you use a Brush. Brushes are similar to Pens in the sense that they define colors and patterns for the area to fill. However, Brushes come in much more complex configurations. For instance, there are gradient brushes, texture brushes, and brushes based on bitmap images.

You use the Graphics object to draw text strings and you use it to draw and manipulate images. And much, much more. I won’t use this article to introduce the intricacies of GDI+. I will simply discuss the functionality in my examples. If you’re new to GDI+, I encourage you to read my article, “The Basics of GDI+” in this issue. Assuming that you understand the basics, this article will show you how to apply GDI+ functionality to Web applications.

Let’s explore some basic GDI+ features using a Windows application. To follow along with my example, create a new C# Windows Form application in Visual Studio .NET.

When you create a new C# Windows Form application, you start out with a default Form class. As I mentioned above, GDI+ operates through a Graphics object, which the .NET Framework defines in the System.Drawing namespace. This is the namespace that represents GDI+. When you create a Windows Forms application you don’t have to worry about using that namespace because all Windows Forms use GDI+ and the namespace is therefore imported by default.

So how do you get access to a Graphics object that allows you to draw on the form? Well, you can create an event handler for the Paint event, which your application will raise every time the operating system asks the form to re-draw itself. The event arguments that you pass to this event handler have a reference to the form’s Graphics object. The following sample code uses the Paint event to draw an ellipse on the form:

   private void Form1_Paint(object sender,    System.Windows.Forms.PaintEventArgs e)   {      Graphics g = e.Graphics;      g.DrawEllipse(Pens.Red,      10,10,150,100);   }

In this code I simply call the DrawEllipse() method and pass a red pen as well as the position and the size of the ellipse. The red pen is a default pen defined in the .NET Framework. As you can imagine, the result is not spectacular (Figure 1).

Our First Web Example
Start by creating a C# Web application. By default, Visual Studio .NET creates a first Web Form. You cannot use that Web Form to draw on directly because Web Forms are glorified HTML pages that can only do what HTML browsers can interpret. However, you can use the default form to host the drawing example you’ll create.

Whatever you create with GDI+ on the Web server will be sent to the client as a bitmap. In fact, the client does not know that the graphic it is about to display is generated on-the-fly using GDI+. Therefore, you can use a simple tag to refer to the image. But what is the image’s name? Since you’ll create the image on-the-fly, the image’s name is actually another ASP.NET page. Confused? Just bare with me! Add the following tag to your default Web Form (WebForm1.aspx). To do so, switch to HTML view:

   

Now, add a new Web Form to your project called “Sample1.aspx.” The new form automatically contains some HTML. Since you’ll generate an image rather than HTML, you do not want the HTML that was automatically created. Therefore, switch into HTML view and remove the HTML in that file, leaving only the following line in the aspx file (which is required, because it links the aspx file to the code-behind file):

   <%@ Page language="c#"        Codebehind="Sample1.aspx.cs"         AutoEventWireup="false"         Inherits="GDIPlusArticle.Sample1" %>

In my examples, I use code-behind files for the actual code I’ll write. I do this because I think it is cleaner, and also because Visual Studio .NET does so automatically. If you would rather use inline-code (as is the case if you use another editor such as Web Matrix), you can. Where the code resides has no influence on the actual functionality described here.

Right-click on the page and select View Code. The code editor shows some default code. You want the Page_Load event handler method. (Note that, by default, the System.Drawing namespace is included at the very top. In addition, you may want to include the System.Drawing.Imaging namespace to avoid a lot of typing.) The basic idea is that you want to create a blank Bitmap object from scratch, then retrieve a Graphics handle (object) from it, and draw the ellipse on it (see Listing 1).

The Bitmap object is an in-memory image. You generate this image object by creating an instance of the Bitmap class and you then pass the size of the new bitmap as parameters to the constructor.

You retrieve the Graphics object by calling the static FromImage() method on the Graphics class (with the Bitmap object passed as a parameter). Once you have the Graphics object, there is no difference in the drawing code. Drawing on an in-memory bitmap is identical to drawing on a window (or any other GDI+ drawing canvas for that matter). Note that a new bitmap, by default, is all black (all bits are set to 0). Since this most definitely is not the look you’re going for, you’ll also “clear” the image background by setting the bits to 1 and producing a white background. You didn’t have to take this step in the Windows Form version since the default background color was fine (although you can do the same thing if you want to). The rest of the code is identical to the code you used in the Windows Form.

You should next ask, “How do I send the image back to the client?” The answer is: As the current “page.” “But,” you may say, “ASP.NET pages are HTML pages.” This statement is true in most cases because it’s the default behavior. In reality you can make an ASP.NET page any type of data. In this case the data type is an image and the image format you’ll chose is JPEG. You can change the data type of the aspx page by setting the ContentType property of the Response object to “image/jpeg” (or “image/gif” if you want to send a GIF formatted image). This way the browser that hits the “page” will interpret the returned data as binary image information.

Drawing on Existing Images
Once you refresh the page a few times, the excitement fades away and you’ll realize that all you did was create a silly ellipse. So let’s do something more exciting!

So far I’ve only shown you how to draw on new images. I’ve shown you some very useful functionality if you want to create graphics from scratch to draw diagrams and charts. The next examples, however, will show you how to load existing images and manipulate them on the fly. Let’s start out with the basics. Let’s assume you run a Web site that provides up-to-date news on sporting events. On the home page of your site you want to display a picture of some sports event and the current score (Figure 3).

Rendering Graphical Buttons
One maintenance nightmare that occurs on many Web sites is rendering graphical buttons. Figure 4 and Figure 5 show graphical buttons I use on my personal site (http://www.MarkusEgger.com). You can probably already imagine how this is done. Listing 3 shows the detailed code (this time in Visual Basic .NET).

Image Quality
I want to briefly discuss image quality. Consider the rounded red rectangle in Figure 6. The rectangle highlights an area but it is not part of the actual image that gets generated. It is generated dynamically similar to the other images that I’ve shown you how to create in this article. The main difference is that the rectangle is on a white background, which makes it harder to make the text look crisp. Also, the chosen color ends up looking “rastered” using the default rendering settings. Therefore, I took some extra steps to make sure the quality ends up at an acceptable level.

A Simple Photo Album
I’m going to take what you’ve learned so far and write a simple photo album application. Let’s say you want to write an ASP.NET page that will display all the image files in a directory, and add formatting to display the images as you would see them in a strip of film. You can easily retrieve a list of all files using the following command:

   System.IO.Directory.GetFiles( _      Path,"*.jpg")

Once you retrieve a list of files, you can generate a list of tags, such as the following:

   

Listing 5 shows the code to create the film strip effect. It will first create a black drawing canvas. Then the code creates a second image to use as a brush to draw the whole at the top and the bottom of the film strip. This bitmap is as tall as the main film strip, but only as wide as a single hole. The code draws the holes using rounded white rectangles with a thick enough Pen to make them look like filled rectangles (or holes). Finally, the code creates a new texture brush based on that image and fills the entire area with that texture. Voila! You’ve created a film strip.

Next the code loads the actual image and determines its size and orientation. Based on that information, the code calculates the shrink-factor for the thumbnail image, which the code creates then draws on the canvas with an appropriate placement to center the thumbnail on the film strip. Finally, the code renders a copyright notice and streams the file to the client.

Note: Bitmap objects have a native method to generate thumbnail images. Depending on your situation, you may be better of using the Bitmap object’s native method to create thumbnails. This technique often performs better because the method can retrieve thumbnail information that may already be in the image. In this example however, I chose not to do that in order to have more control over the generated thumbnail.

You can see the result in Figure 8, or on my personal Web site (http://www.MarkusEgger.com). If you go to my Web site and look at the pictures from Chichen Itza (as shown in Figure 8), you will see about 50 thumbnail images. Each of those images (before my code turns them into thumbnails) is about 2MB in size. When you hit that page, you will make ASP.NET plow through about 100MB of data. The resulting performance is very reasonable. In fact, on my local machine, the Web site generates the thumbnails with the extra film strip effect faster than Windows Explorer can display a thumbnail view of the same folder. It’s quite amazing.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist

©2024 Copyright DevX - All Rights Reserved. Registration or use of this site constitutes acceptance of our Terms of Service and Privacy Policy.