Dynamically Add Text to Images Retrieved from the Database using an ASP.NET Http Handler

Posted by: Suprotim Agarwal , on 10/13/2008, in Category ASP.NET
Views: 66706
Abstract: We often create applications where we retrieve images from the database and display it on the page. At times, we may need to add some text or a copyright notice dynamically on the images. This article discusses how to do so using an ASP.NET Http Handler.
Dynamically Add Text to Images Retrieved from the Database using an ASP.NET Http Handler
We often create applications where we retrieve images from the database and display it on the page. At times, we may need to add some text or a copyright notice dynamically on the images. This article discusses how to do so using an ASP.NET Http Handler.
We will be using the data from the Employees table of the Northwind database since it contains images.
Note: I am using Visual Studio 2008 and I have targeted the application to use .NET 3.5
Step 1: Open VS 2008. Click File > New > Website. Choose ASP.NET Website from the list of installed template, choose target platform as .NET Framework 3.5, choose the desired language and enter the location where you would like to store the website on your FileSystem. I have created a folder called VS2008 Projects, so the location over here is C:\VS2008 Projects\AddTextToImages. After typing the location, click OK.
Step 2: Since we are retrieving the images from the database, we would need a connection string. Add the following connection string to your web.config
            <add name="NorthwindConnectionString" connectionString="Data Source=(local);Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient"/>
Step 3: We will be using an HttpHandler to pull images and then add some text to the retrieved images. I just love using handlers to handle scenarios like these as they provide me with a lot of flexibility while accessing server-side resources. To create an Http handler, right click project > Add New Item > Generic Handler > TextOnImageHandler.ashx. Add the following code to the handler.
<%@ WebHandler Language="C#" Class="TextOnImageHandler" %>
using System;
using System.Web;
using System.Drawing;
using System.Configuration;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Data;
using System.Data.SqlClient;
public class TextOnImageHandler : IHttpHandler {
    byte[] empPic = null;
    long seq = 0;
    public void ProcessRequest(HttpContext context)
        Int32 empno;
        if (context.Request.QueryString["id"] != null)
            empno = Convert.ToInt32(context.Request.QueryString["id"]);
            throw new ArgumentException("No parameter specified");
        // Convert Byte[] to Bitmap
        Bitmap newBmp = ConvertToBitmap(ShowEmpImage(empno));
        // Watermark Text to be added to image
        string text = "Code from dotnetcurry";
        if(newBmp != null)
           Bitmap convBmp = AddTextToImage(newBmp, text);
           convBmp.Save(context.Response.OutputStream,  ImageFormat.Jpeg);
    // Add Watermark Text to Image
    protected Bitmap AddTextToImage(Bitmap bImg, string msg)
        // To void the error due to Indexed Pixel Format
        Image img = new Bitmap(bImg, new Size(bImg.Width, bImg.Height));
        Bitmap tmp = new Bitmap(img);
        Graphics graphic = Graphics.FromImage(tmp);
        // Watermark effect
        SolidBrush brush = new SolidBrush(Color.FromArgb(120, 255, 255, 255));
        // Draw the text string to the Graphics object at a given position.
        graphic.DrawString(msg, new Font("Times New Roman", 14, FontStyle.Italic),
             brush, new PointF(10, 30));
        return tmp;
    // Convert byte array to Bitmap (byte[] to Bitmap)
    protected Bitmap ConvertToBitmap(byte[] bmp)
        if(bmp != null)
        TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
        Bitmap b = (Bitmap)tc.ConvertFrom(bmp);
        return b;
    public byte[] ShowEmpImage(int empno)
        string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
        SqlConnection connection = new SqlConnection(conn);
        string sql = "SELECT photo FROM Employees WHERE EmployeeID = @ID";
        SqlCommand cmd = new SqlCommand(sql, connection);
        cmd.CommandType = CommandType.Text;
        cmd.Parameters.AddWithValue("@ID", empno);
        SqlDataReader dr = cmd.ExecuteReader();
        if (dr.Read())
            seq = dr.GetBytes(0, 0, null, 0, int.MaxValue) - 1;
            empPic = new byte[seq + 1];
            dr.GetBytes(0, 0, empPic, 0, Convert.ToInt32(seq));
        return empPic;
    public bool IsReusable
            return false;
<%@ WebHandler Language="vb" Class="TextOnImageHandler" %>
Imports System
Imports System.Web
Imports System.Drawing
Imports System.Configuration
Imports System.ComponentModel
Imports System.Drawing.Imaging
Imports System.Data
Imports System.Data.SqlClient
Public Class TextOnImageHandler
      Implements IHttpHandler
      Private empPic() As Byte = Nothing
      Private seq As Long = 0
      Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            Dim empno As Int32
            If context.Request.QueryString("id") IsNot Nothing Then
                  empno = Convert.ToInt32(context.Request.QueryString("id"))
                  Throw New ArgumentException("No parameter specified")
            End If
            ' Convert Byte[] to Bitmap
            Dim newBmp As Bitmap = ConvertToBitmap(ShowEmpImage(empno))
            ' Watermark Text to be added to image
            Dim text As String = "Code from dotnetcurry"
            Dim convBmp As Bitmap = AddTextToImage(newBmp, text)
            convBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg)
      End Sub
      ' Add Watermark Text to Image
      Protected Function AddTextToImage(ByVal bImg As Bitmap, ByVal msg As String) As Bitmap
            ' To void the error due to Indexed Pixel Format
            Dim img As Image = New Bitmap(bImg, New Size(bImg.Width, bImg.Height))
            Dim tmp As New Bitmap(img)
            Dim graphic As Graphics = Graphics.FromImage(tmp)
            ' Watermark effect
            Dim brush As New SolidBrush(Color.FromArgb(120, 255, 255, 255))
            ' Draw the text string to the Graphics object at a given position.
            graphic.DrawString(msg, New Font("Times New Roman", 14, FontStyle.Italic), brush, New PointF(10, 30))
            Return tmp
      End Function
      ' Convert byte array to Bitmap (byte[] to Bitmap)
      Protected Function ConvertToBitmap(ByVal bmp() As Byte) As Bitmap
         If bmp IsNot Nothing Then 
            Dim tc As TypeConverter = TypeDescriptor.GetConverter(GetType(Bitmap))
            Dim b As Bitmap = CType(tc.ConvertFrom(bmp), Bitmap)
            Return b
         End If
         Return Nothing
      End Function
      Public Function ShowEmpImage(ByVal empno As Integer) As Byte()
            Dim conn As String = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString
            Dim connection As New SqlConnection(conn)
            Dim sql As String = "SELECT photo FROM Employees WHERE EmployeeID = @ID"
            Dim cmd As New SqlCommand(sql, connection)
            cmd.CommandType = CommandType.Text
            cmd.Parameters.AddWithValue("@ID", empno)
            Dim dr As SqlDataReader = cmd.ExecuteReader()
            If dr.Read() Then
                  seq = dr.GetBytes(0, 0, Nothing, 0, Integer.MaxValue) - 1
                  empPic = New Byte(seq){}
                  dr.GetBytes(0, 0, empPic, 0, Convert.ToInt32(seq))
            End If
            Return empPic
      End Function
      Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
                  Return False
            End Get
      End Property
End Class
The steps for adding some text to the image, using the handler are as follows:
1.    The EmployeeID whose image is to be retrieved, is passed to the handler via query string. We use the Request.QueryString[“id”] to retrieve the EmployeeID(emp_id) from the handler url. The ID is then passed to the ‘ShowEmpImage()’ method where the image is fetched from the database using SqlDataReader and returned in a byte[] object.
2.    We pass this byte[] to the ConvertToBitmap() function where we use the TypeConverter class to convert a byte array to bitmap.
3.    We then pass the bitmap and the text to be written on the Bitmap, to the AddTextToImage() method. If the image has an indexed pixel format, then directly calling the method Graphics.ShowImage() would throw an exception with the message, "A Graphics object cannot be created from an image that has an indexed pixel format”. A workaround is to create a temporary bitmap with the same width and height as that of the original bitmap and then create a new Graphics object from the Image.
4.    We then use the Graphics.DrawString() to draw the specified string at the specified location. The watermark effect is achieved using an alpha component of 120 provided in the Color.FromArgb() method.
5.    The last step is to save the image to the page's output stream and indicate the image format as shown here convBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg)
You can call this handler in the following way:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Write Text On Image</title>
    <form id="form1" runat="server">
         <img alt="Image" id="img1" src="TextOnImageHandler.ashx?id=2" />
The image with the watermark text will look similar to the following (Notice the watermark text 'Code from dotnetcurry'):
Text Image Handler
The entire source code of the article in C# and VB.NET can be downloaded from here. I hope you liked the article and I thank you for viewing it.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for ten consecutive times. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn

Page copy protected against web site content infringement 	by Copyscape

Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by karu7310 on Saturday, December 27, 2008 3:14 AM
Good Job........
Comment posted by Tajudeen Iwalola on Wednesday, February 11, 2009 7:37 AM
Thanks for these beautiful codes. I have not try the code on my server. My question is how can you display other form fields like: first name, last name, date of birth, state of origing , sex, marital status and other customers details. I mean the information should be submitted to mssql or ms access that base, and before submission, the image and that has to be preview. On submission the image and data submitted should be displayed on the brower. I t would be highly appreciated if u can come up with these codes. i have gone theough the web i hv not seen such a codes....Tajudeen Iwalola mobile 2348056410758
Comment posted by manu on Tuesday, April 7, 2009 12:55 PM
i want to know how can we retrieve the embedded text from the image back is there ane method to do it?
Comment posted by guru on Friday, September 24, 2010 12:25 PM

Thank you so much for the code. I made some changes so i can have 4 images on each other.

My question is my httphandler works fine on the localhost without even adding anything to the web.config file. But it doesnt work when I deployed the website? I am using iss7. Do I have to register this to the web.config file to make it work? if so how. Since this is my first handler. Also how would I install/map it to iis7.

Also I would have to create a .dll file to do it but I am not sure if i just compile the .ashx file it will just make it into a .dll file.

Thank you very much

Comment posted by SVK on Wednesday, May 4, 2011 6:55 AM
this code is extremely good & beneficial
i tried the same & tred some modification
i want even the text msg from the database
i tried to retirvive the msg from databse in
public void ProcessRequest(HttpContext context) event

but it was giving me error
and secondly i dont want the omage to be watermarked , & in the code it has a id called from aspx page , how do i naviagte thr; multiple  images & get differnet text stored in db

Comment posted by Mark Hipwell on Wednesday, April 11, 2012 8:57 AM
What is it with .NET developers? Why are you, as an MCDBA, accessing, or encouraging others to access, an SQL database using inline SQL? The only way anyone should ever access an SQL database is via stored procedures. Anyone reading this who does not know all the reasons why using inline SQL is bad practice has no place doing even basic static HTML web pages, let alone trying to teach others bad habits! Not impressed.
Comment posted by Suprotim Agarwal on Thursday, April 12, 2012 8:14 AM
@markhipwell - point taken. I do not want to go into the old Stored Proc vs Inline sql debate, but in scenarios like these, where a single line of code is needed, if I have to write one SP for every line, it can become a maintenance nightmare. The inline sql bad practice that you mention can be corrected with parameterized queries!

Having said that, I totally agree that SP's bring additional security and I personally prefer writing SP's in my apps. This scenario simply did not demand one!





C# Book for Building Concepts and Interviews



jQuery CookBook