给图片添加水印,一般的做法是在上传图片时直接给图片添加上水印,由于我在项目中使用了FCKeditor,在上传时不易控制,同时对方还要求他们自己用时不能有水印,于是我就使用了在图片显示时动态添加水印的办法,另外,为了提高效率,还使用了缓存技术,这样不必每次都添加水印,节省时间和提高性能。

本文中使用到的类是IHttpHandler(准确地说是一个接口),msdn对它的定义是:“定义 ASP.NET 为使用自定义 HTTP 处理程序同步处理 HTTP Web 请求而实现的协定。”HTTP处理程序是实现了System.Web.IHttpHandler接口的.NET组件,任何实现了IHttpHandler接口的类都可以用于处理输入的HTTP请求。也就是每次我们请求asp.net网站上的资源,都会由这个请求处理,这样就好控制了。

我的做法是,实现IHttpHandler接口,由实现这个接口的ImageHandler类专门处理对图片资源的请求,第一次请求某个图片时,由于缓存中没有,就读取这个图片,添加上我们指定的水印(由web.config设置指定),然后把输出到客户端,同时也把它缓存一定时间,在缓存期内就再次请求这个图片就不用添加水印了,直接把缓存中的图片输出就行了。

首先我们要编写自己的类ImageHandler实现IHttpHandler接口,代码如下:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Drawing;
using System.Drawing.Imaging;

/// <summary>
///ImageHandler 的摘要说明
/// </summary>
public class ImageHandler:IHttpHandler
{
 public ImageHandler()
 {
  //
  //TODO: 在此处添加构造函数逻辑
  //
 }

    #region IHttpHandler 成员

    public bool IsReusable
    {
        get { return true ; }
    }

    public void Proce***equest(HttpContext context)
    {
        string p_w_picpathpath = context.Request.PhysicalPath;
        Bitmap p_w_picpath = null;
        if (context.Cache[p_w_picpathpath] == null)
        {
            p_w_picpath = new Bitmap(p_w_picpathpath);
            p_w_picpath = AddWaterMark(p_w_picpath);
            context.Cache[p_w_picpathpath] = p_w_picpath;
        }
        else
        {
            p_w_picpath = context.Cache[p_w_picpathpath] as Bitmap;
        }
        p_w_picpath.Save(context.Response.OutputStream, ImageFormat.Jpeg);
    }
    //给图片添加水印
    private Bitmap AddWaterMark(Bitmap p_w_picpath)
    {
        string text = System.Configuration.ConfigurationManager.AppSettings["WaterMark"].ToString();
        int fontSize = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Font-Size"].ToString());
        Font font = new Font("宋体", fontSize);

        //Brush brush = Brushes.DarkGray;
        Brush brush = Brushes.Red;
        Graphics g = Graphics.FromImage(p_w_picpath);
        SizeF size = g.MeasureString(text, font);
        g.DrawString(text, font, brush, p_w_picpath.Width - size.Width, p_w_picpath.Height - size.Height);
        g.Dispose();
        return p_w_picpath;
    }


    #endregion
}
 

可以把这个类编译成一个单独的dll文件,不过我现在是演示,直接放在了App_Code文件夹下了。

html页面如下:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>无标题页</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <img src="Images/1.jpg" /><br />
    <img src="Images/2.jpg" /><br />
    <img src="3.jpg" /><br />
    </div>
    </form>
</body>
</html>
最后我们还需要对web.config做一些配置,一是定义我们要添加的水印文字,二是定义文字大小,三是将我们自己的HttpHandler注册到网站,我的web.config文件如下:
 

<? xml version="1.0" ?>
<!--  
    注意: 除了手动编辑此文件以外,您还可以使用 
    Web 管理工具来配置应用程序的设置。可以使用 Visual Studio 中的
     “网站”->“Asp.Net 配置”选项。
    设置和注释的完整列表在 
    machine.config.comments 中,该文件通常位于 
    WindowsMicrosoft.NetFrameworkv2.xConfig 中
-->
< configuration >
    
< appSettings >
        
<!-- 添加到图片上的水印文字 -->
        
< add  key ="WaterMark"  value ="公司网址" />
        
<!-- 水印文字的字体大小 -->
        
< add  key ="Font-Size"  value ="14" />
    
</ appSettings >
    
< connectionStrings />
    
< system .web >
         < compilation  debug ="true" />
        
<!--
            通过 <authentication> 节可以配置 ASP.NET 使用的 
            安全身份验证模式,
            以标识传入的用户。 
        
-->
        
< authentication  mode ="Windows" />
         < httpHandlers >
      
<!-- 只处理UploadImages目录下的jpg文件,别的目录下的图片不处理 -->
            
< add  path ="Images/*.jpg"  verb ="*"  type ="ImageHandler" />
        
</ httpHandlers >
    
</ system.web >
</ configuration >
 
在web.comfig中我添加了3处,在<appSettings>节点中的配置我就不细说了,主要说说<httpHandlers>节点中的配置,在这里我的配置是:
<add path="Images/*.jpg" verb="*" type="ImageHandler"/>

它表明只处理网站根目录下的Images文件夹中的图片,在本实例中Upload文件夹也有图片,可是这个文件夹下的图片是网站logo等常规图片,不需要处理,所以这个元素的path属性值是:path="Images/*.jpg",如果你想给所有jpg图片添加水印,可以写成path="*.jpg",在接下来的页面中我们就会看到结果如我们所愿,在Upload目录下的图片真的没有添加水印,而在Images确实添加了水印!

 

最后说明:(一)在这儿我将水印文字字体设置为14,同时还是用了醒目的红色,在实际项目中需要根据图片大小计算文字大小,文字颜色不宜过于鲜明;(二)为了演示,缓存使用过于简单,还可以进行一些更负责的设置,更大程度节省内存。(三)添加水印图片原理也很简单,使用GDI+将水印图片画在要添加水印的图片上即可;(四)即使单独在地址栏输入图片的url地址,看到的图片也一样会有水印。