ImageCanvas Web User Control for ASP.NET

Most of you must have seen picture box control of windows forms. We can set image of picture box control and control will render that image in form.


Introduction: 

Sending dynamic image content to browser has always been tricky issue. With System.Drawing namespace available to ASP.Net creating images on fly has become relatively simpler. In normal case we would use aspx page to stream image to web form like

<img src="somePage.aspx?id=12"/>

Now for image to be dynamic we need to pass some information to aspx page, which we are doing by passing query string, but some time if we need to pass several information at a time through query string things can get can get complicated.

So what other options we have?

Most of you must have seen picture box control of windows forms. We can set image of picture box control and control will render that image in form.

What if we can create user control, which works in same way, we can pass image and it renders image on browser?

WebForm:

Our web form should look like following. It should have two ImageCanvas controls (Which we are going to create) and in Page_Load event we should be able to pass images to those controls. 

<%@ Page Language="C#" %>
<%@ Register TagPrefix="Portal" TagName="ImageCanvas" Src="ImageCanvas.ascx" %>
<%@ import Namespace="System.Drawing" %>
<script runat="server">
void Page_Load(Object sender, EventArgs e)
{
Bitmap bitmap1 =
new Bitmap(200,30);
Graphics g = Graphics.FromImage(bitmap1);
g.Clear(Color.White);
g.DrawString("C-SharpCorner(First)",
new Font
"Verdana",10),System.Drawing.Brushes.Black,5,5);
ImageCanvas1.bitmap = bitmap1;
Bitmap bitmap2 =
new Bitmap(200,30);
Graphics g2 = Graphics.FromImage(bitmap2);
g2.Clear(Color.White);
g2.DrawString("C-SharpCorner(Second)",
new Font
"Verdana",10),System.Drawing.Brushes.Red,5,5);
ImageCanvas2.bitmap = bitmap2;
}
</script>
<html>
<head>
</head>
<body>
<form runat="server" ID="Form1">
<PORTAL:ImageCanvas id="ImageCanvas1" runat="server" ImageType="Gif" /> <PORTAL:ImageCanvas id="ImageCanvas2" runat="server" ImageType="Jpeg" /> </form>
</body>
</html>

UserControl :

Now in order to achieve what we have written in web form. Lets write code for User control that can render image which we have passed in page load event of web form.

We have UserContol ImageCanvas.ascx and we will put Image WebControl on that UserControl.

<asp:Image id="DyImage" runat="server" ></asp:Image>

In page load event of usercontrol we would write following code.

string Url = Request.Url.ToString();
if (Url.IndexOf("?") == -1)
{
DyImage.ImageUrl = Url + "?" + ID + "=Show";
}
else
{
DyImage.ImageUrl = Url + "&" + ID + "=Show";
}

What we are doing hear is getting Url of parent form we are adding new query string to that url with name as ID of UserControl and value set to Show and then setting ImageUrl of our Image Web control to that Url. 

What would happen by doing this?  When our page is loaded control will render following html to browser

<img id="ImageCanvas1_DyImage" src="http://www.xyz.com /ImgCanvasSample.aspx?ImageCanvas1=Show" border="0" />

As you can see this image is pointing to same page but it now has additional query string with name as ID of our usercontrol and value Show. Putting name as ID of userControl will allow us to use more then one image control on same page.

Now we will add some more code to our user control first to provide facility to user to define which type of image he wants And another to send binary stream of image. This will complete our code for user Control.

<%@ Control Language="C#" %>
<%@ Control Language="C#" %>
<%@ import Namespace="System.Drawing" %>
<%@ import Namespace="System.Drawing.Imaging" %>
<script runat="server">

public Bitmap bitmap;
public ContentType ImageType = ContentType.Jpeg;
void Page_Load(Object sender, EventArgs e)
{
if (Request.Params[ID] != null)
{
Response.Clear();
Response.ContentType = "Image/" + ImageType.ToString();
bitmap.Save(Response.OutputStream,getFormat((
int)ImageType));
Response.End();
}
String Url = Request.Url.ToString();
if (Url.IndexOf("?") == -1)
{
DyImage.ImageUrl = Url + "?" + ID + "=Show";
}
else
{
DyImage.ImageUrl = Url + "&" + ID + "=Show";
}
}
ImageFormat getFormat(
int i)
{
ImageFormat imgfmt = ImageFormat.Jpeg;
switch(i)
{
case 0:
imgfmt = ImageFormat.Gif;
break;
case 1:
imgfmt = ImageFormat.Jpeg;
break;
case 2:
imgfmt = ImageFormat.Png;
break;
}
return imgfmt;
}
public enum ContentType
{
Gif=0,Jpeg=1,Png=2
}

</script>
<asp:Image id="DyImage" runat="server" ></asp:Image>

As you can see we have added some more code to Page_Load event of userControl which would read for Query string and stream binary image to browser, we also have defined Enum for ContentType that user can choose to render type of image they want.

Result :

Following is screen shot of our web form, which displays two dynamic images we created on Page_Load event of the web form.

Caution: 

I would not consider this technique as standard for displaying dynamic Images I would rather call this as a workaround when we are unable to pass complicated data (through query string) to generate Image dynamically, because some part of code in this case is processed more then one time to achieve what we were looking for.