This will be a first of a couple posts about this ImageHandler and ways it can be used.
At times I’ve worked for different very creative and artistic companies (here, here, here and here) and during those times I have wanted to watermark an image for one reason or another. Either the image was protected and was not supposed to be redistributed or the client just wanted to make sure their URL was present on the image. The reasons are plentiful.
The image(s) I’m using in this project is the logo for the company I work for.
You can download the handler and a sample web site to run this handler in at the bottom of this post.
How To
I’ve written a quick example of how to watermark all images (jpg, png, gif or bmp) on a web site.
It uses a simple HttpHandler that you can drop into the App_Code folder of your ASP.NET Project. With a quick addition to your web.config file you start using this.
Video
To understand what I’m saying, watch this screen cast (this screen cast has no sound):
Now lets look at some code…
Code
(web.Config)
<?xml version="1.0"?> <configuration> <system.web> <httpHandlers> <add verb="GET" type="ImageHandler" path="*.jpg,*.png,*.gif,*.bmp"/> </httpHandlers> <compilation debug="true"/></system.web> </configuration>
ImageHandler.cs
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Net.Mime; using System.IO; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; /// <summary> /// Summary description for ImageHandler /// </summary> public class ImageHandler : IHttpHandler { public ImageHandler() { } public string GetContentType(String path) { switch (Path.GetExtension(path)) { case ".bmp": return "Image/bmp"; case ".gif": return "Image/gif"; case ".jpg": return "Image/jpeg"; case ".png": return "Image/png"; default: break; } return String.Empty; } public ImageFormat GetImageFormat(String path) { switch (Path.GetExtension(path).ToLower()) { case ".bmp": return ImageFormat.Bmp; case ".gif": return ImageFormat.Gif; case ".jpg": return ImageFormat.Jpeg; case ".png": return ImageFormat.Png; default: return null; } } protected byte[] WatermarkImage(HttpContext context) { byte[] imageBytes = null; if (File.Exists(context.Request.PhysicalPath)) { // Normally you'd put this in a config file somewhere. string watermark = "John Doe - © EXAMPLE Company 2007"; Image image = Image.FromFile(context.Request.PhysicalPath); Graphics graphic; if (image.PixelFormat != PixelFormat.Indexed &&
image.PixelFormat != PixelFormat.Format8bppIndexed &&
image.PixelFormat != PixelFormat.Format4bppIndexed &&
image.PixelFormat != PixelFormat.Format1bppIndexed) { // Graphic is not a Indexed (GIF) image graphic = Graphics.FromImage(image); } else { /* Cannot create a graphics object from an indexed (GIF) image. * So we're going to copy the image into a new bitmap so * we can work with it. */ Bitmap indexedImage = new Bitmap(image); graphic = Graphics.FromImage(indexedImage); // Draw the contents of the original bitmap onto the new bitmap. graphic.DrawImage(image, 0, 0, image.Width, image.Height); image = indexedImage; } graphic.SmoothingMode = SmoothingMode.AntiAlias & SmoothingMode.HighQuality; Font myFont = new Font("Arial", 15); SolidBrush brush = new SolidBrush(Color.FromArgb(80, Color.White)); /* This gets the size of the graphic so we can determine * the loop counts and placement of the watermarked text. */ SizeF textSize = graphic.MeasureString(watermark, myFont); // Write the text across the image. for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { PointF pointF = new PointF(x, y); graphic.DrawString(watermark, myFont, brush, pointF); x += Convert.ToInt32(textSize.Width); } y += Convert.ToInt32(textSize.Height); } using (MemoryStream memoryStream = new MemoryStream()) { image.Save(memoryStream, GetImageFormat(context.Request.PhysicalPath)); imageBytes = memoryStream.ToArray(); } } return imageBytes; } #region IHttpHandler Members public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { context.Response.Clear(); context.Response.ContentType = GetContentType(context.Request.PhysicalPath); byte[] imageBytes = WatermarkImage(context); if (imageBytes != null) { context.Response.OutputStream.Write(imageBytes, 0, imageBytes.Length); } else { // No bytes = no image which equals NO FILE. :) // Therefore send a 404 - not found response. context.Response.StatusCode = 404; } context.Response.End(); } #endregion }
Explanation
With the configuration above, we will capture all jpg, png, gif and bmp images as they are requested from the HttpRequest object.
As we encounter the image, we find it, then create an image and graphics object from it and then loop through the images height/width ratio and write some text on top of the image.
A key note about watermarking. You can simply write some text over the screen but then the image behind it would not be visible. You should ensure that the font you’re overlaying is transparent therefore the image shows through the font that is on top. This is done by using the Color.FromArgpb method, which is in this piece of code:
Color.FromArgb(80, Color.White)
The “80” is a alpha value. Valid values are 0-255. If you’re at 0, the color is invisible. If you’re at 255, the color is solid. Here, I’m using 80. You can see the text, but you can see through it. Play with this number to see what works best for you.
Conclusion
Its easy to watermark images in ASP.NET. In future posts I’ll show you how to protect certain directories images as well as how to do some other cool stuff with it like denying access (anti-leech and leech re-routing).
Download ImageHandler.zip (1.57 KB) (This is just the cs file)
Download Example ImageHandlerDemoSite.zip (84.7 KB) (Demo site for demonstration)
Ti says
Hola
Gscloete says
hi,
this is a very good example, but can you make one for IIS7.5 on a website please? I am struggeling to get the demo converted.
guest47 says
Your screen cast 404’s and the demo doesn’t seem to do anything other than display the images in the folder…..your watermarking code isn’t even being called…..
haha says
authentic nfl jerseys Inexpensive items
coach bags on sale I am confident with his
coach outlet store online First step in success
coach outlet online Workmanship
coach bags outlet Value of goods
coach outlet store Of love
wholesale designer bags Beautiful lines
coach bags outlet There range of children
cheap coach What are you waiting
wholesale nfl jerseys Is always expected
authentic nfl jerseys It is pretty good
ZL says
Awesome article!! help me a lot! I’ve converted it into a WAP model.
Please reference the github project.
https://github.com/ZeviLiao/ImageHandlerDemoProject
for anyone who need it. many thanks!!
sunil kumar says
Not working after deployment in server.????????????????