Watermarking Images On The Fly Using ASP.NET
Watermarking and general image manipulation within the .NET Framework has become quite an easy thing to carry out thanks to the features provided by the System.Drawing namespace. The System.Drawing namespace contains types to help you with…well…drawing and rendering images. I will not be covering the basic use of the System.Drawing class. But feel free to carry out a Google.
My example consists of using a .NET (aspx) page and a Generic Handler (ashx). The .NET page will allow me to select an image, add a logo to the top left and some text. The Generic Handler will contain all the magic needed to manipulate the image based on selections made within the .NET page. The screenshot (below) shows my basic program in action.
Firstly, let me start off by showing you the code for the Generic Handler.
ImageRenderJpeg.ashx
using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
public class ImageRenderJpeg : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
//Retrieve image details
string imageUrl = context.Request.QueryString["ImageUrl"].ToString();
string imageComment = context.Request.QueryString["ImageComment"].ToString();
string imageIconUrl = context.Request.QueryString["Icon"].ToString();
if (!String.IsNullOrEmpty(imageUrl))
{
//Get the location of the image
Image imagePhoto = Image.FromFile(imageUrl);
// Get dimensions of image
int imageHeight = imagePhoto.Height;
int imageWidth = imagePhoto.Width;
//Create a new Bitmap
Bitmap oBitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format24bppRgb);
//Load Background Graphic from Image
Graphics oGraphics = Graphics.FromImage(oBitmap);
oGraphics.SmoothingMode = SmoothingMode.HighQuality;
oGraphics.DrawImage(imagePhoto, new Rectangle(0, 0, imageWidth, imageHeight), 0, 0, imageWidth, imageHeight, GraphicsUnit.Pixel);
//Layer 1: Add an Image Logo to the top left
if (!String.IsNullOrEmpty(imageIconUrl))
{
Image imageIcon = Image.FromFile(imageIconUrl);
oGraphics.DrawImage(imageIcon, new Rectangle(5, 5, 124, 48), 0, 0, imageIcon.Width, imageIcon.Height, GraphicsUnit.Pixel);
imageIcon.Dispose();
}
//Layer 2: Add Comment
if (!String.IsNullOrEmpty(imageComment))
{
Font commentFont = new Font("Arial", 14, FontStyle.Regular); //Font Style
StringFormat commentFormat = new StringFormat();
commentFormat.Alignment = StringAlignment.Near; //Align text in left of layer
SolidBrush commentBrush = new SolidBrush(Color.Black); //Font Colour
oGraphics.FillRectangle(Brushes.Beige, 5, imageHeight - 55, imageWidth - 15, 50); //Create a rectangle with white background
oGraphics.DrawString(imageComment, commentFont, commentBrush, new Rectangle(5, imageHeight - 55, imageWidth - 15, 50), commentFormat); //Add comment text inside rectangle
}
//Layer 3: Add Copyright watermark
Font watermarkFont = new Font("Arial", 40, FontStyle.Bold); //Font Style
SolidBrush semiTransBrush = new SolidBrush(Color.LightGray); //Font Colour
StringFormat watermarkFormat = new StringFormat();
watermarkFormat.Alignment = StringAlignment.Center; //Align text in center of image
oGraphics.DrawString("Copyright",
watermarkFont,
semiTransBrush,
new PointF(imageWidth / 2, imageHeight / 2), watermarkFormat);
//Dispose of graphic objects
imagePhoto.Dispose();
oGraphics.Dispose();
//Output image
oBitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
else
{
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
You can see that I am manipulating my image based on the query string parameters I pass from my .NET page into my Generic Handler. Hopefully, my code is commented well enough to explain the general overview on what is going on.
The following code displays how my aspx page parses all the parameters needed to generate an image on the page:
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_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>Image Generator</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Select an Image:
<asp:DropDownList ID="ddlImage" runat="server">
<asp:ListItem Text="*" Value="*">Select Image</asp:ListItem>
<asp:ListItem Text="The Tumbler" Value="C:\Users\Surinder\Documents\Visual Studio 2010\WebSites\ImageCreator\Images\batmobile_Tumbler.jpg"></asp:ListItem>
<asp:ListItem Text="Audi TT" Value="C:\Users\Surinder\Documents\Visual Studio 2010\WebSites\ImageCreator\Images\new-audi-tt-coupe.jpg"></asp:ListItem>
<asp:ListItem Text="Volvo Concept" Value="C:\Users\Surinder\Documents\Visual Studio 2010\WebSites\ImageCreator\Images\volvo-s60-concept-interior1.jpg"></asp:ListItem>
</asp:DropDownList>
<br />
<br />
Add Logo: <asp:TextBox ID="txtImage" runat="server"></asp:TextBox>
<br />
<br />
Add a comment:
<asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine" Width="500" Height="50"></asp:TextBox>
<br />
<br />
<asp:Button ID="btnCreateImage" Text="Create Image" runat="server" onclick="btnCreateImage_Click" />
<br />
<br />
<img id="imgRender" alt="Image Render" title="Image Render" runat="server" />
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (ddlImage.SelectedValue == "*")
{
imgRender.Visible = false;
}
else
{
imgRender.Visible = true;
}
}
protected void btnCreateImage_Click(object sender, EventArgs e)
{
if (ddlImage.SelectedValue != "*")
{
//The Image source will be pointed to our Generic Handler to display the image.
imgRender.Src = String.Format("ImageRenderJpeg.ashx?ImageUrl={0}&ImageComment={1}&Icon={2}", ddlImage.SelectedValue, txtComment.Text, txtImage.Text);
}
}
}