Many of us already use GDI functionalities to dynamically render an image on the server with some custom font.
I bet most of you just create a fake ASPX page that creates the image, then you make your <img> or <asp:Image> tags point to the fake page as the image source.
What about turning it all into a handy and reusable Custom Control?
Let's start with a new control library and put in a HttpHandler.
We will use it to render the image and output as binary data to the OutputStream.
It will be just a class implementing the IHttpHandler interface.
Everything we would do in the page's Load event must be done within the ProcessRequest method in our handler.
Here is a sample.
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Web;
namespace DynamicImage
{
class ImageRenderer : IHttpHandler
{
private string _text
{
get { return HttpContext.Current.Request["text"]; }
}
private string _fontName
{
get { return HttpContext.Current.Request.QueryString["fontName"]; }
}
private int _fontSize
{
get { return int.Parse(HttpContext.Current.Request.QueryString["fontSize"]); }
}
private Color _foreColor
{
get { return ColorTranslator.FromHtml(HttpContext.Current.Request.QueryString["foreColor"]); }
}
private Color _backColor
{
get { return ColorTranslator.FromHtml(HttpContext.Current.Request.QueryString["backColor"]); }
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
// fake bitmap to get needed size
Bitmap bitmap = new Bitmap(1, 1);
int width = 0;
int height = 0;
// create font object with requested properties
Font font = new Font(_fontName,
_fontSize,
FontStyle.Regular);
// create the graphics object to measure text size and perform actual rendering
Graphics graphics = Graphics.FromImage(bitmap);
// get needed size to render the wanted text
SizeF size = graphics.MeasureString(_text, font);
width = (int)size.Width;
height = (int)size.Height;
// release resources
graphics.Dispose();
bitmap.Dispose();
// create the actual bitmap with final size
bitmap = new Bitmap(width, height);
// render text
graphics = Graphics.FromImage(bitmap);
graphics.Clear(_backColor);
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.DrawString(_text,
font,
new SolidBrush(_foreColor),
0,
0);
graphics.Flush();
// create codec object for jpg format
ImageCodecInfo jpegCodec = null;
foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
if (codec.MimeType == "image/jpeg")
{
jpegCodec = codec;
break;
}
// set codec quality
EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, (long)100);
// output the binary data to the output stream
bitmap.Save(context.Response.OutputStream, jpegCodec, parameters);
// release resources
graphics.Dispose();
bitmap.Dispose();
}
}
}
Now, to test the handler, we create a new Web project, add a reference to our newly created Control Library, and register our HttpHandler in web.config file as follows:
<httpHandlers>
<add path="image.ashx" verb="GET" type="DynamicImage.ImageRenderer"/>
</httpHandlers>
Let's get it working in the browser.
Navigate to the following path in your test site:
image.ashx?text=Hello World&fontName=Verdana&fontSize=18&foreColor=yellow&backColor=red
This should render the "Hello World" text with a yellow-on-red color.
Fine, this was the first step, nothing really new.
Now we are going to add a WebControl that will encapsulate the rendering functionalities, just converting a series of custom properties to the correct url.
Let's add a new server control to the library.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Web.UI;
namespace DynamicImage
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DynamicImage runat=server></{0}:DynamicImage>")]
public class DynamicImage : System.Web.UI.WebControls.Image
{
public string Text { get; set; }
public string FontName { get; set; }
public int FontSize { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
ImageUrl = string.Format("image.ashx?text={0}&fontName={1}&fontSize={2}&foreColor={3}&backColor={4}",
Text,
FontName,
FontSize,
ColorTranslator.ToHtml(ForeColor),
ColorTranslator.ToHtml(BackColor));
}
}
}
Last step: register the custom control in our test site web.config file:
<pages>
<controls>
<add tagPrefix="my" namespace="DynamicImage" assembly="DynamicImage" />
</controls>
</pages>
We are done! Let's try it out on a page:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="DynamicImage_Default" %>
<!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>My Dynamic Image</title>
</head>
<body>
<form id="form1" runat="server">
<div>
This is my dynamic image:
<my:DynamicImage
runat="server"
Text="Hello World"
FontName="Verdana"
FontSize="18"
ForeColor="Yellow"
BackColor="Red"
/>
</div>
</form>
</body>
</html>
That's it. Now we have a dynamic image renderer, which we can easily reuse in any project of ours.
Hope you will find it useful in your web applications.
Happy coding!
Source code available here: DynamicImage.zip (3.27 kb)