Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Community Wiki

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Navigation

Google Ads

ASP.NET: Drawing images and bar charts with System.Drawing

From Wiki

Jump to: navigation, search


Summary: An example of how we can create an image and even bar charts by using the System.Drawing namespace.

Drawing your own images in ASP.NET can be achieved by using what is known as GDI+. To work with GDI+, we can use the System.Drawing namespace which provides direct access to GDI+ basic graphics functionality.

For this example, we'll be working specifically with the System.Drawing.Graphics namespace which will allow us to draw rectangles and lines.

To demonstrate these methods, we'll create a simple example that simply draws a rectangle out to our page. Firstly, we'll need to import these two namespaces:

  1. Imports System.Drawing  
  2. Imports System.Drawing.Imaging

Then, let's create a simple 100x100 image with a small rectangle inside it:

  1. Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  2.     ' Tell the page to expect an image  
  3.     Response.ContentType = "image/JPEG"
  4.  
  5.     ' Create a new 100x100 bitmap and graphics object  
  6.     Dim b As New Bitmap(100, 100)
  7.     Dim g As Graphics = Graphics.FromImage(b)
  8.  
  9.     ' Add a 20x20 white square  
  10.     g.DrawRectangle(Pens.White, 20, 20, 20, 20)
  11.  
  12.     ' Stream the image out to the client  
  13.     b.Save(Response.OutputStream, ImageFormat.Jpeg)
  14. End Sub

When you run this code on your development machine, you should hopefully see a small image with the rectangle drawn inside it. To do this, you'll notice that we used the Graphics.DrawRectangle method to draw a rectangle specified by a coordinate pair, a width, and a height.

Now that we've gone through a simple example of creating a rectangle, we can then take this knowledge and build a series of rectangles to form a bar chart. First, we need to create a page that will contain an image. This image will point at our bar chart page which will return the bar chart image. We'll also pass the x and y axis values to this page as part of the querystring so that the bar chart page knows what to create. I'm just going to be hard-coding these values for this example but, if you wanted, you could make the image runat="server" or use an asp:Image control so that you can set the values from your code-behind page. Anyway, here's the example page:

  1. <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default1.aspx.vb" Inherits="Default1" %>  
  2.  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  4.  
  5. <html xmlns="http://www.w3.org/1999/xhtml" >  
  6. <head runat="server">  
  7.     <title>Untitled Page</title>  
  8. </head>  
  9. <body>  
  10.     <form id="form1" runat="server">  
  11.     <div>  
  12.         <img src="barchart.aspx?xaxis=A,B,C,D,E,F,G,H,I,J,K&yaxis=2,4,6,8,10,12,14,16,18,20,22" alt="bar chart"/>  
  13.     </div>  
  14.     </form>  
  15. </body>

As you'll see from above, we've simply set up a comma seperated list of x and y values which will form the basis of our bar chart page. We don't need any code in the aspx portion of our bar chart page as it will be the code behind page that is responsible for outputting the image. So, create a new page called barchart.aspx and add the following code to the code behind page:

  1. Imports System.Drawing
  2. Imports System.Drawing.Imaging
  3.  
  4. Partial Class BarChart
  5. Inherits(System.Web.UI.Page)
  6.     Private rndColor As New Random
  7.  
  8.     Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  9.         ' Declarations  
  10.         Dim intSpacing As Integer = 40
  11.         Dim intBarWidth As Integer = 20
  12.         Dim intBarScale As Integer = 10
  13.         Dim intMaxHeight As Integer = 0
  14.         Dim intMaxWidth As Integer = 0
  15.         Dim gWidth As Graphics = Graphics.FromImage(New Bitmap(1, 1))
  16.         Dim strYAxis As String()
  17.         Dim strXAxis As String()
  18.  
  19.         ' 1) Get an array of each axis value and description  
  20.         strYAxis = Request.QueryString("yaxis").Split(",")
  21.         strXAxis = Request.QueryString("xaxis").Split(",")
  22.  
  23.         ' 2) Get the maximum height for the chart  
  24.         For intHeights As Integer = 0 To strYAxis.Length - 1
  25.             If CInt(strYAxis(intHeights)) > intMaxHeight Then intMaxHeight = CInt(strYAxis(intHeights))
  26.         Next
  27.  
  28.         ' 3) Add 40 pixels to it to compensate for the labels  
  29.         intMaxHeight = intMaxHeight * intBarScale + 40
  30.  
  31.         ' 4) Get the maximum width of any x or y axis string to work out the bar chart width  
  32.         For intWidths As Integer = 0 To strXAxis.Length - 1
  33.             If CInt(gWidth.MeasureString(strXAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) > intMaxWidth Then
  34.                 intMaxWidth = CInt(gWidth.MeasureString(strXAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width)
  35.             End If
  36.         Next
  37.         For intWidths As Integer = 0 To strYAxis.Length - 1
  38.             If CInt(gWidth.MeasureString(strYAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) > intMaxWidth Then
  39.                 intMaxWidth = CInt(gWidth.MeasureString(strYAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width)
  40.             End If
  41.         Next
  42.         intBarWidth = intMaxWidth
  43.  
  44.         ' 5) Create a new bitmap and graphics object based on the size of the number of arrary elements  
  45.         Dim b As New Bitmap(CInt((strXAxis.Length * intBarWidth) + (strXAxis.Length * intSpacing) + (intSpacing / 2)), intMaxHeight)
  46.         Dim g As Graphics = Graphics.FromImage(b)
  47.  
  48.         ' 6) Set the background colour  
  49.         g.Clear(Color.White)
  50.  
  51.         ' 7) Draw each bar  
  52.         For i As Integer = 0 To strYAxis.Length - 1
  53.             ' Add a border for the coloured bar  
  54.             g.DrawRectangle(Pens.Black, (i * intSpacing) + (i * intBarWidth) + 15, _
  55.             intMaxHeight - (CInt(strYAxis(i)) * intBarScale), intBarWidth, (CInt(strYAxis(i)) * intBarScale))
  56.             ' Add the coloured bar  
  57.             g.FillRectangle(New SolidBrush(RandomRGBColor), (i * intSpacing) + (i * intBarWidth) + 15, _
  58.             intMaxHeight - (CInt(strYAxis(i)) * intBarScale), intBarWidth, (CInt(strYAxis(i)) * intBarScale))
  59.             ' Add the x axis values to the bar chart  
  60.             g.DrawString(strXAxis(i), New Font("Courier New", 10, FontStyle.Italic), Brushes.Black, _
  61.                 New PointF((i * intSpacing) + (i * intBarWidth) + 15, intMaxHeight - 25 - (CInt(strYAxis(i)) * intBarScale)))
  62.             ' Add the y axis values to the bar chart  
  63.             g.DrawString(strYAxis(i), New Font("Courier New", 10, FontStyle.Italic), Brushes.White, _
  64.                 New PointF((i * intSpacing) + (i * intBarWidth) + 15, intMaxHeight - (CInt(strYAxis(i)) * intBarScale)))
  65.         Next
  66.  
  67.         ' 8) Add a border to the chart  
  68.         g.DrawRectangle(Pens.Black, 1, 1, _
  69.         CInt((strXAxis.Length * intBarWidth) + (strXAxis.Length * intSpacing) + (intSpacing / 2)) - 2, intMaxHeight - 2)
  70.  
  71.         ' 9) Stream the image out to the client  
  72.         b.Save(Response.OutputStream, ImageFormat.Jpeg)
  73.  
  74.     End Sub
  75.  
  76.     Public Function RandomRGBColor() As Color
  77.         ' Return a random color.  
  78.         Return (Color.FromArgb(255, rndColor.Next(0, 255), rndColor.Next(0, 255), rndColor.Next(0, 255)))
  79.     End Function
  80.  
  81. End Class

You can run that page on your own machine and see the resulting bar chart, but before you do that let's go through the nine steps that were taken to create this image:

1) Get an array of each axis value and description

As we passed the x and y values through to the page as querystring values, we need to split each one to get an array which we can use to find each corresponding value. We could also put some validation into this section to make sure that we have an equal number of values for each axis.

2) Get the maximum height for the chart

In order to work our the size of the bitmap that we need to draw, we loop through each value of the y axis and get the largest value. We can then assign this value to the height attribute of the bitmap.

3) Add 40 pixels to it to compensate for the labels

Before we assign the height, we add 40 pixels to the maximum height so that it allows us a bit of extra room to add the x axis values above each bar.

4) Get the maximum width of any x or y axis string to work out the bar chart width

To work out the width of each bar, I've employed a technique that uses the Graphics.MeasureString method to work out the maximum width of a string from either the x or y axis.

5) Create a new bitmap and graphics object based on the size of the number of array elements

We can now calculate the height and width of our bar chart based on factors such as the number of elements in our array, each bar size, the maximum height and the spacing between each bar.

6) Set the background colour

As you'll have noticed in our very first example, the default colour of the background was black, so using the Graphics.Clear method we can clear the entire drawing surface and fill it with the specified background color.

7) Draw each bar

There are 4 stages to this section.

The first will draw a rectangle based on the size of the y axis value also taking into account an Integer value called "intBarScale". This scale will be used to scale the value up by the relevant number of pixels (i.e. a value of 1 will become 10 if the scale is set to 10). The border of this rectangle will be set to black so that it appears around the coloured bar.

The second stage will create a rectangle of the same size, but no border will added and instead of using the Graphics.DrawRectangle method, we'll use Graphics.FillRectangle so that we can fill it with a random colour.

The third stage will add the x axis value just above the relevant bar and the fourth stage will add the y axis value just inside the bar itself.

8) Add a border to the chart

Here we use the same technique as above to draw a black border around the whole image.

9) Stream the image out to the client

We can now stream this image back to the calling page and set the image type.

As you can see from this example, it's relatively easy to draw images once you know how to interact with the Graphics namespace. There are some enhancements that you will need to make if you wanted to use this page for creating bar charts in a production environment (which you'll see if you start modifying the values that are passed through to the bar chart page) but I think it should be a very good starting point and you can now hopefully use this knowledge for any other image needs you have.


This Hack is part of the ASP.NET Hacks collection

458 Rating: 4.0/5 (13 votes cast)