7.12 Dynamically Render an Image


Problem

You need to render dynamic graphics (perhaps to build the output for a chart or graph control).

Solution

Build the graphic using GDI+ and an in-memory System.Drawing.Bitmap object. Then you can write it to the page output stream, or you can save it to the server's hard drive and display it with an Image Web control.

Discussion

You can draw dynamic graphics using the same GDI+ code in a Web application that you'd use in a Windows-based application. The only difference is how you render the final graphic. There are basically two approaches that you can use.

  • You can stream the binary contents of the image directly to the OutputStream property of the HttpResponse object. This is a good approach if you need to generate a wide range of images and don't want to clutter the server hard drive with image files that won't be used again. It's also the best choice if you need to create dynamic images that are tailored to match user input.

  • You can save the image to the Web server's file system and use an HTML < img > tag to display the created image. This is a good choice if you need to create a graphic that will be reused because it will avoid the overhead of continuously re-creating the graphic.

This recipe explores both approaches. First we'll consider how to dynamically create an image without saving it to a file. In this example, the goal is to create a simple banner (as shown in Figure 7.8).

click to expand
Figure 7.8: A dynamically generated banner.

You'll notice that the only user-supplied value in this example is the banner text itself, which is supplied through the query string. The font, colors, and dimensions are hard-coded (although they could easily be set based on other query string parameters or Web.config defaults).

Here's the full page code:

 using System; using System.Web; using System.Web.UI.WebControls; using System.Drawing; using System.Drawing.Drawing2D; public class DynamicGraphic : System.Web.UI.Page {     // (Designer code omitted.)     private void Page_Load(object sender, System.EventArgs e) {              // Get the text from the query string.         // If no text is supplied, choose a default.         string text = "";         if (Request.QueryString["image"] == null) {                      Response.Redirect(Request.Url + "?image=" +             Server.UrlEncode("This is a test image"));         }         else {             text = Server.UrlDecode(Request.QueryString["image"]);         }    // Create an in-memory bitmap where you will draw the image.              // The Bitmap is 300 pixels wide and 200 pixels high.                int width = 300, height = 200;             Bitmap bitmap = new Bitmap(width, height);             // Get the graphics context for the bitmap.             Graphics graphics = Graphics.FromImage(bitmap);             // Set the background color and rendering quality.             // This color will become the border             graphics.Clear(Color.OrangeRed);             graphics.SmoothingMode = SmoothingMode.AntiAlias;             // Paint a rectangle.             graphics.FillRectangle(new SolidBrush(Color.Olive), 5, 5,                width - 10, height - 10);             // Choose a font and alignment for the text.             Font fontBanner = new Font("Verdana", 24, FontStyle.Bold);             StringFormat stringFormat = new StringFormat();             stringFormat.Alignment = StringAlignment.Center;             stringFormat.LineAlignment = StringAlignment.Center;             // Paint the text.             graphics.DrawString(text, fontBanner, new              SolidBrush(Color.LightYellow), new Rectangle(0, 0, width, height),                stringFormat);             // Render the image to the HTML output stream.             bitmap.Save(Response.OutputStream,                System.Drawing.Imaging.ImageFormat.Gif);             graphics.Dispose();             bitmap.Dispose();         }     } } 

When you save an image to the response stream, you replace any other output. Therefore, you can't use this technique with a page that also includes Web controls or static HTML content. Thus, if you want to use a page that combines dynamically generated images and Web controls, you need to wrap the dynamically generated image in a control or write the image to the hard drive before displaying it.

If you want to save the file to the hard drive, you move the image generation code into a separate method, which we'll call GenerateBanner . Then, in the Page.Load event handler, you begin by checking to see whether the file already exists by using the static File.Exists method. If the file doesn't exist, you generate it in memory by calling GenerateBanner and save it using the Bitmap.Save method. Otherwise, you simply load the image directly.

The following code shows the basic approach you must take:

 using System; using System.IO; using System.Web; using System.Web.UI.WebControls; using System.Drawing; using System.Drawing.Drawing2D; public class DynamicGraphic : System.Web.UI.Page {     protected System.Web.UI.WebControls.Image imageControl;     // (Designer code omitted.)     private Bitmap GenerateBanner() {              // Create the image using the same code as in the previous example.         // (Code omitted.)     }         private void Page_Load(object sender, System.EventArgs e) {              // Set the filename based on the image text.         // We assume this only includes characters that are         // legal for a filename.         string fileName = Request.QueryString["image"] + ".gif";         Bitmap bitmap = null;         // Check if an image with this text already exists.         if (File.Exists(fileName)) {             // Load the existing image.             try {                 bitmap = new Bitmap(fileName);             }catch {                 bitmap = GenerateBanner();             }         }         else {             bitmap = GenerateBanner();             // Save the image.             bitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Gif);         }         // Display the image by setting an Image property.         imageControl.ImageUrl = fileName;     } } 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net