Blog

Tagged by 'ashx'

  • 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.

    Image Watermarking

    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);
            }
        }
    }