Introduction
A picture is worth thousands of words. This is especially true when filling certain web forms of situation-describing nature where an image could illustrate the main text effectively. Situations such as insurance form filling (car, house), or diagnosis (machinery, patient), situation assessment (accident, traffic, map), etc. would love to see simple image annotation capabilities added to the existing online web forms. In this article, I will show you a simple and effective way to annotate images on the web form, using ASP.NET.
How it works
To tackle such a problem, we divide it into two requirements:
- enable the image on the form to receive (x, y) coordinates as positions of the annotation;
- enable the server-side code to draw appropriate overlay onto the original image and render it to the browser.
Now does this sound a lot simpler?
For (1), we do not need to embed any client-side ActiveX component etc. to record simple (x, y) coordinates resulted from mouse clicks. <asp:ImageButton>
would do the job very well. It supports an onClick(object sender, ImageClickEventArgs e)
event. Properties of the e
event argument object are:
e.x
(integer
) - X coordinate where the click took place.
e.y
(integer
) - Y coordinate where the click took place.
Or even simpler, after we create a server-side ImageButton
in the form:
<asp:ImageButton id="MarkupImage" runat="server"
ImageUrl="Markup.aspx?desc="></asp:ImageButton>
calling the next two lines would retrieve the required (x, y) coordinate information on the server side.
string x=Request.Params["MarkupImage.x"];
string y=Request.Params["MarkupImage.y"];
Now (2). If the user selects a type of annotation (e.g., rectangle) and supply relevant arguments (e.g., width and height), he/she would click once on the image to add the annotation. After getting the (x, y) information from the mouse click, we would update the ImageUrl
property of the ImageButton
and make it point to another aspx file Markup.aspx that is responsible for rendering the original image with any overlay or annotation specified at the position of mouse click. For simplicity, all markup/annotation information including position, type and applicable arguments are encoded as a single URL parameter desc
, each annotation object being semicolon delimited. For example, it could be:
ImageUrl="Markup.aspx?desc=136,187,0,8,8;267," +
"254,1,3;138,282,2,TEXT;269,336,3,left.ico;";
It consists of four markups. The first one is "136,187,0,8,8;" being a rectangle of 8x8 at (136,187). The second one is "267,254,1,3;" being a circle of radius=3 at (267,254). The third one "138,282,2,TEXT;" means a 'TEXT' string at (138,282), while the last one "269,336,3,left.ico;" draws the image 'left.ico' onto (269,336); the file left.ico is on the server.
Setting ImageURL
would cause the src
attribute of the rendered HTML <input type="image">
in the browser pointing to Markup.aspx and that page is requested. Rendering the image is quite simple as we can load and manipulate images through the GDI+ managed class interface (a set of wrappers of Win32 GDI+ API).
private void Page_Load(object sender, System.EventArgs e)
{
string desc = HttpUtility.HtmlDecode(Request.Params["desc"]);
if (desc == null)
{
desc = string.Empty;
}
MarkupImage("LocalMap.jpg", desc);
}
private void MarkupImage(string image, string desc)
{
Bitmap bitmap = new Bitmap(Server.MapPath(image));
MemoryStream memStream = new MemoryStream();
Graphics g = Graphics.FromImage(bitmap);
Response.Clear();
Response.ContentType="image/jpeg";
bitmap.Save(memStream, ImageFormat.Jpeg);
memStream.WriteTo(Response.OutputStream);
g.Dispose();
bitmap.Dispose();
}
Simple, isn't it?
The drawing for each type of annotation such as rectangle, circle, text, image etc. is using standard GDI+ functions, therefore would not be discussed in detail here and please refer to the source code. Of course, you could easily support many other types.
Points of Interest
In this article, we explored a mechanism to perform simple image annotation in the ASP.NET web form. It is achieved by reading the positional information of mouse click from the ImageButton
control and assigning its ImageUrl
attribute to another ASP.NET page with annotation information encoded into the URL parameter. The second page would subsequently render using GDI+ on the server-side and output it to the browser with ContentType="image/jpeg"
. This functionality could be useful in situations to complement pure text web to illustrate details worth thousands of words.
History
- Sep-Oct 2004, first draft.