If you would like to hire my services, you can now do so by visiting the following link:
Website Design Darlington
Article Statistics
Code Bank Statistics
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: Imports System.Drawing Imports System.Drawing.Imaging Then, let's create a simple 100x100 image with a small rectangle inside it: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load ' Tell the page to expect an image Response.ContentType = "image/JPEG" ' Create a new 100x100 bitmap and graphics object Dim b As New Bitmap(100, 100) Dim g As Graphics = Graphics.FromImage(b) ' Add a 20x20 white square g.DrawRectangle(Pens.White, 20, 20, 20, 20) ' Stream the image out to the client b.Save(Response.OutputStream, ImageFormat.Jpeg) 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: <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default1.aspx.vb" Inherits="Default1" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <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"/> </div> </form> </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: Imports System.Drawing Imports System.Drawing.Imaging Partial Class BarChart Inherits System.Web.UI.Page Private rndColor As New Random Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Declarations Dim intSpacing As Integer = 40 Dim intBarWidth As Integer = 20 Dim intBarScale As Integer = 10 Dim intMaxHeight As Integer = 0 Dim intMaxWidth As Integer = 0 Dim gWidth As Graphics = Graphics.FromImage(New Bitmap(1, 1)) Dim strYAxis As String() Dim strXAxis As String() ' 1) Get an array of each axis value and description strYAxis = Request.QueryString("yaxis").Split(",") strXAxis = Request.QueryString("xaxis").Split(",") ' 2) Get the maximum height for the chart For intHeights As Integer = 0 To strYAxis.Length - 1 If CInt(strYAxis(intHeights)) > intMaxHeight Then intMaxHeight = CInt(strYAxis(intHeights)) Next ' 3) Add 40 pixels to it to compensate for the labels intMaxHeight = intMaxHeight * intBarScale + 40 ' 4) Get the maximum width of any x or y axis string to work out the bar chart width For intWidths As Integer = 0 To strXAxis.Length - 1 If CInt(gWidth.MeasureString(strXAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) > intMaxWidth Then intMaxWidth = CInt(gWidth.MeasureString(strXAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) End If Next For intWidths As Integer = 0 To strYAxis.Length - 1 If CInt(gWidth.MeasureString(strYAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) > intMaxWidth Then intMaxWidth = CInt(gWidth.MeasureString(strYAxis(intWidths), New Font("Courier New", 10, FontStyle.Italic)).Width) End If Next intBarWidth = intMaxWidth ' 5) Create a new bitmap and graphics object based on the size of the number of arrary elements Dim b As New Bitmap(CInt((strXAxis.Length * intBarWidth) + (strXAxis.Length * intSpacing) + (intSpacing / 2)), intMaxHeight) Dim g As Graphics = Graphics.FromImage(b) ' 6) Set the background colour g.Clear(Color.White) ' 7) Draw each bar For i As Integer = 0 To strYAxis.Length - 1 ' Add a border for the coloured bar g.DrawRectangle(Pens.Black, (i * intSpacing) + (i * intBarWidth) + 15, _ intMaxHeight - (CInt(strYAxis(i)) * intBarScale), intBarWidth, (CInt(strYAxis(i)) * intBarScale)) ' Add the coloured bar g.FillRectangle(New SolidBrush(RandomRGBColor), (i * intSpacing) + (i * intBarWidth) + 15, _ intMaxHeight - (CInt(strYAxis(i)) * intBarScale), intBarWidth, (CInt(strYAxis(i)) * intBarScale)) ' Add the x axis values to the bar chart g.DrawString(strXAxis(i), New Font("Courier New", 10, FontStyle.Italic), Brushes.Black, _ New PointF((i * intSpacing) + (i * intBarWidth) + 15, intMaxHeight - 25 - (CInt(strYAxis(i)) * intBarScale))) ' Add the y axis values to the bar chart g.DrawString(strYAxis(i), New Font("Courier New", 10, FontStyle.Italic), Brushes.White, _ New PointF((i * intSpacing) + (i * intBarWidth) + 15, intMaxHeight - (CInt(strYAxis(i)) * intBarScale))) Next ' 8) Add a border to the chart g.DrawRectangle(Pens.Black, 1, 1, _ CInt((strXAxis.Length * intBarWidth) + (strXAxis.Length * intSpacing) + (intSpacing / 2)) - 2, intMaxHeight - 2) ' 9) Stream the image out to the client b.Save(Response.OutputStream, ImageFormat.Jpeg) End Sub Public Function RandomRGBColor() As Color ' Return a random color. Return Color.FromArgb(255, rndColor.Next(0, 255), rndColor.Next(0, 255), rndColor.Next(0, 255)) End Function 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 descriptionAs 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 chartIn 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 labelsBefore 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 widthTo 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 elementsWe 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 colourAs 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 barThere 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 chartHere we use the same technique as above to draw a black border around the whole image.9) Stream the image out to the clientWe 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.
Posted on 15/05/2007 01:55:20
1. Grant 01/06/2007 12:09:23
Badabing! Good one. So, could you use this to say create a bar chart from values stored in a database?Also, is there any way to modify the background color of the image to something other than black?
2. Mark Smith 02/06/2007 02:57:40
Grant,The "xaxis" and "yaxis" values are simply passed through to the page as a querystring value. You can easily modify these and pass through whatever values you want.The background colour is set in step #6 by passing the relevant colour to the Graphics.Clear method.Mark
Please keep your comments relevant to this page. Any inappropriate or purely promotional comments may be removed. Email addresses are never displayed but are required so you can confirm your comments.