代码改变世界

ASP.NET 图片加水印,水印位置自定义

2010-09-02 19:40  音乐让我说  阅读(1233)  评论(6编辑  收藏  举报

VS目录:

代码如下:

Default.aspx 页面

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ImageWaterMark._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></title>
    <style type="text/css">
        .imgFload { float:left; }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        请选择图片:<asp:FileUpload ID="fuImage" runat="server" /><br />
        请输入水印图片的位置:<asp:DropDownList ID="ddlWaterImgPosition" runat="server" AppendDataBoundItems="true" DataTextField="EnumDisplayText" DataValueField="EnumValue">
        </asp:DropDownList><br />
        <asp:Button ID="btnSubmit" runat="server" Text="提交" OnClick="btnSubmit_Click" />
        <asp:Button ID="btnRecut" runat="server" Text="重新裁剪" OnClick="btnRecut_Click" Visible="false"/>
    </div>
    <div style="float:left;">
        <asp:Image ID="imgResult" runat="server" Visible="false" CssClass="imgFload" />
        <asp:PlaceHolder ID="phImgContainer" runat="server"></asp:PlaceHolder>
    </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;
using System.IO;

namespace ImageWaterMark
{
    public partial class _Default : System.Web.UI.Page
    {

        /// <summary>
        /// 图像集合
        /// </summary>
        public List<string> ImgFilePathList
        {
            get
            {
                return ViewState["ImgFilePathList"] == null ? new List<string>() : (List<string>)ViewState["ImgFilePathList"];
            }
            set
            {
                ViewState["ImgFilePathList"] = value;
            }
        }

        /// <summary>
        /// 加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if(!IsPostBack)
            {
                this.ddlWaterImgPosition.DataSource = EnumDescription.GetFieldTexts(typeof(ImagePosition));
                this.ddlWaterImgPosition.DataBind();
            }
        }

        /// <summary>
        /// 提交
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            ImagePosition imagePosition = (ImagePosition)Convert.ToInt32(this.ddlWaterImgPosition.SelectedValue);
            string dateTimeStr = DateTime.Now.ToString("yyyyMMddHHmmssmmm");
            string saveVirualPath = "~/images/" + dateTimeStr;
            string errorMessage;
            bool flag = CommonClass.ValidateImgExtensionAndSave(this.fuImage, ref saveVirualPath, out errorMessage, false, true, 1);
            if(!flag)
            {
                this.ClientScript.RegisterStartupScript(btnSubmit.GetType(), "", "alert('" + errorMessage + "')", true);
                return;
            }
            string newSavedVirualPath = "~/modifiedImages/" + dateTimeStr + ".jpg";
            string newSavedPhysicalPath = Server.MapPath(newSavedVirualPath);
            flag = CoverWaterImage.MakeCoverWaterImage(Server.MapPath(saveVirualPath), newSavedPhysicalPath, out errorMessage, imagePosition);
            if(!flag)
            {
                this.ClientScript.RegisterStartupScript(btnSubmit.GetType(), "", "alert('" + errorMessage + "')", true);
                return;
            }
            this.imgResult.Visible = true;
            this.btnRecut.Visible = true;
            this.imgResult.ImageUrl = newSavedVirualPath;
        }

        /// <summary>
        /// 重新裁剪
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnRecut_Click(object sender, EventArgs e)
        {
            ImagePosition imagePosition = (ImagePosition)Convert.ToInt32(this.ddlWaterImgPosition.SelectedValue);
            string savedVirualPath = this.imgResult.ImageUrl;
            string fileName = Path.GetFileName(savedVirualPath);
            string newSavedVirualPath = "~/modifiedImages/" + DateTime.Now.ToString("yyyyMMddHHmmssmmm") + ".jpg";
            string newSavedPhysicalPath = Server.MapPath(newSavedVirualPath);
            string errorMessage;
            bool flag = CoverWaterImage.MakeCoverWaterImage(Server.MapPath("~/images/" + fileName), newSavedPhysicalPath, out errorMessage, imagePosition);
            if (!flag)
            {
                this.ClientScript.RegisterStartupScript(btnSubmit.GetType(), "", "alert('" + errorMessage + "')", true);
                return;
            }
            List<string> imgList = ImgFilePathList;
            imgList.Add(newSavedVirualPath);
            foreach (string item in imgList)
            {
                Image imgNew = new Image();
                imgNew.ImageUrl = item;
                this.phImgContainer.Controls.Add(imgNew);
            }
            ImgFilePathList = imgList;
        }
    }
}

 

CommonClass.cs 代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using System.IO;
using System.Drawing;

namespace ImageWaterMark
{
    public class CommonClass
    {
        /// <summary>
        /// 验证图片的真实类型,并尝试保存图片
        /// </summary>
        /// <param name="hifile">FileUpload 控件ID</param>
        /// <param name="savedVirtualPath">要保存图片的虚拟路径(虚拟路径不能包括扩展名,正确的写法比如"/video/2010/5/中国人"),如果上传失败,则保存的路径为空</param>
        /// <param name="errorMessage">如果上传失败,错误消息</param>
        /// <param name="allowFileEmpty">是否允许FileUpload没有文件,如果允许,则当FileUpload为空时,不显示错误信息</param>
        /// <param name="limitImgSize">是否限制图片的大小,true表示限制</param>
        /// <param name="imgSize_MB">如果限制图片的大小成立,即参数“limitImgSize”的值为True,则最大能允许的图片的兆数(MB)</param>
        /// <returns>验证结果,true表示成功,false表示失败</returns>
        public static bool ValidateImgExtensionAndSave(FileUpload hifile, ref string savedVirtualPath, out string errorMessage, bool allowFileEmpty, bool limitImgSize, double imgSize_MB)
        {
            if (hifile != null && hifile.HasFile)
            {
                Stream streamInput = hifile.PostedFile.InputStream;

                BinaryReader r = new BinaryReader(streamInput);
                string fileclass = "";
                byte buffer;
                try
                {
                    buffer = r.ReadByte();
                    fileclass = buffer.ToString();
                    buffer = r.ReadByte();
                    fileclass += buffer.ToString();
                    //r.Close();
                }
                catch (Exception)
                {
                    r.Close();
                    streamInput.Close();
                    errorMessage = "读取文件流失败,请确定您文件的正确性!";
                    savedVirtualPath = string.Empty;
                    return false;
                }
                //说明255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar
                if (fileclass == "255216" || fileclass == "7173" || fileclass == "6677" || fileclass == "13780")
                {
                    //成功
                    if (limitImgSize)
                    {
                        //限制图片的大小
                        double imgSize = (double)streamInput.Length / (1024 * 1024);
                        if (imgSize > imgSize_MB)
                        {
                            errorMessage = "图片的大小最大不能超过" + imgSize_MB + "M";
                            savedVirtualPath = string.Empty;
                            streamInput.Close();
                            return false;
                        }
                    }
                    string imgExtension = string.Empty;
                    System.Drawing.Imaging.ImageFormat imgFormat;
                    switch (fileclass)
                    {
                        case "255216":
                            imgExtension = ".jpg";
                            imgFormat = System.Drawing.Imaging.ImageFormat.Jpeg;
                            break;
                        case "7173":
                            imgExtension = ".gif";
                            imgFormat = System.Drawing.Imaging.ImageFormat.Gif;
                            break;
                        case "6677":
                            imgExtension = ".bmp";
                            imgFormat = System.Drawing.Imaging.ImageFormat.Bmp;
                            break;
                        case "13780":
                            imgExtension = ".png";
                            imgFormat = System.Drawing.Imaging.ImageFormat.Png;
                            break;
                        default:
                            imgFormat = System.Drawing.Imaging.ImageFormat.Jpeg;
                            break;
                    }
                    System.Drawing.Image img = System.Drawing.Image.FromStream(streamInput);
                    if (savedVirtualPath.LastIndexOf('/') == (savedVirtualPath.Length - 1))
                    {
                        throw new Exception("没有文件名,正确的格式应该比如为:/目录名/.../myImg,其中\"myImg\"表示文件名!");
                    }
                    savedVirtualPath = savedVirtualPath + imgExtension;
                    string physicalImgPath = HttpContext.Current.Server.MapPath(savedVirtualPath);
                    string physicalImgDictionaryPath = physicalImgPath.Substring(0, physicalImgPath.LastIndexOf('\\'));
                    if (!Directory.Exists(physicalImgDictionaryPath))
                    {
                        Directory.CreateDirectory(physicalImgDictionaryPath);
                    }
                    img.Save(HttpContext.Current.Server.MapPath(savedVirtualPath), imgFormat);
                    img.Dispose();
                    streamInput.Close();
                    errorMessage = string.Empty;
                    return true;
                }
                else
                {
                    errorMessage = "图片格式不正确!";
                    savedVirtualPath = string.Empty;
                    return false;
                }
            }
            else
            {
                savedVirtualPath = string.Empty;
                if (allowFileEmpty)
                {
                    //允许上传的文件为空
                    errorMessage = string.Empty;
                    return true;
                }
                else
                {
                    //一定要有文件
                    errorMessage = "没有文件,或文件为空!";
                    return false;
                }
            }
        }

    }
}

 

ImagePosition.cs 代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;

namespace ImageWaterMark
{
    public enum ImagePosition
    {
        /// <summary>
        /// 默认
        /// </summary>
        [EnumDescription("默认",1)]
        Default = 0,

        /// <summary>
        /// 左上方
        /// </summary>
        [EnumDescription("左上方")]
        LeftTop = 1,

        /// <summary>
        /// 正上方
        /// </summary>
        [EnumDescription("正上方")]
        Top = 2,

        /// <summary>
        /// 右上方
        /// </summary>
        [EnumDescription("右上方")]
        RightTop = 3,

        /// <summary>
        /// 左边
        /// </summary>
        [EnumDescription("左边")]
        Left = 4,

        /// <summary>
        /// 正中
        /// </summary>
        [EnumDescription("正中")]
        Middle = 5,
        
        /// <summary>
        /// 右边
        /// </summary>
        [EnumDescription("右边")]
        Right = 6,
        
        /// <summary>
        /// 左下方
        /// </summary>
        [EnumDescription("左下方")]
        LeftBottom = 7,

        /// <summary>
        /// 正下方
        /// </summary>
        [EnumDescription("正下方")]
        Bottom = 8,

        /// <summary>
        /// 右下方
        /// </summary>
        [EnumDescription("右下方")]
        RightBottom = 9
    }
}

 

EnumHelper.cs 代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.ComponentModel;

namespace ImageWaterMark
{
    public class EnumHelper
    {

        /// <summary>
        /// 得到枚举所有字段上面的描述,缺点是如果某个字段没有描述,则对应值时会出错
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <returns></returns>
        public static List<string> GetEnumDescription<T>()
        {
            Type t = typeof(T);
            if(!t.IsEnum)
            {
                throw new ArgumentException("泛型参数必须是枚举类型。");
            }
            FieldInfo[] fieldInfo = t.GetFields();
            List<string> result = new List<string>();
            foreach (FieldInfo item in fieldInfo)
            {
                DescriptionAttribute[] attrObjs = (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrObjs != null && attrObjs.Length > 0)
                {
                    result.Add(attrObjs[0].Description);
                }
            }
            return result;
        }
    }
}

 

EnumDescription.cs 代码如下:

using System;
using System.Reflection;
using System.Collections;
using System.Text;

namespace ImageWaterMark
{
    /// <summary>
    /// 把枚举值按照指定的文本显示
    /// <remarks>
    /// 一般通过枚举值的ToString()可以得到变量的文本,
    /// 但是有时候需要的到与之对应的更充分的文本,
    /// 这个类帮助达到此目的。
    /// </remarks>
    /// </summary>
    /// <example>
    /// [EnumDescription("中文数字")]
    /// enum MyEnum
    /// {
    ///		[EnumDescription("数字一")]
    /// 	One = 1, 
    /// 
    ///		[EnumDescription("数字二")]
    ///		Two, 
    /// 
    ///		[EnumDescription("数字三")]
    ///		Three
    /// }
    /// EnumDescription.GetEnumText(typeof(MyEnum));
    /// EnumDescription.GetFieldText(MyEnum.Two);
    /// EnumDescription.GetFieldTexts(typeof(MyEnum)); 
    /// </example>
    

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)]
    public class EnumDescription : Attribute
    {
        private string enumDisplayText;
        private int enumRank;
        private FieldInfo fieldIno;

        /// <summary>
        /// 描述枚举值
        /// </summary>
        /// <param name="enumDisplayText">描述内容</param>
        /// <param name="enumRank">排列顺序</param>
        public EnumDescription(string enumDisplayText, int enumRank)
        {
            this.enumDisplayText = enumDisplayText;
            this.enumRank = enumRank;
        }

        /// <summary>
        /// 描述枚举值,默认排序为5
        /// </summary>
        /// <param name="enumDisplayText">描述内容</param>
        public EnumDescription(string enumDisplayText)
            : this(enumDisplayText, 5) { }

        public string EnumDisplayText
        {
            get { return this.enumDisplayText; }
        }

        public int EnumRank
        {
            get { return enumRank; }
        }

        public int EnumValue
        {
            get { return (int)fieldIno.GetValue(null); }
        }

        public string FieldName
        {
            get { return fieldIno.Name; }
        }

        /// <summary>
        /// 排序类型
        /// </summary>
        public enum SortType
        {
            /// <summary>
            ///按枚举顺序默认排序
            /// </summary>
            Default,
            /// <summary>
            /// 按描述值排序
            /// </summary>
            DisplayText,
            /// <summary>
            /// 按排序熵
            /// </summary>
            Rank
        }

        private static System.Collections.Hashtable cachedEnum = new Hashtable();


        /// <summary>
        /// 得到对枚举的描述文本
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns></returns>
        public static string GetEnumText(Type enumType)
        {
            EnumDescription[] eds = (EnumDescription[])enumType.GetCustomAttributes(typeof(EnumDescription), false);
            if (eds.Length != 1)
                return string.Empty;
            return eds[0].EnumDisplayText;
        }

        /// <summary>
        /// 获得指定枚举类型中,指定值的描述文本。
        /// </summary>
        /// <param name="enumValue">枚举值,不要作任何类型转换</param>
        /// <returns>描述字符串</returns>
        public static string GetFieldText(object enumValue)
        {
            EnumDescription[] descriptions = GetFieldTexts(enumValue.GetType(), SortType.Default);
            foreach (EnumDescription ed in descriptions)
            {
                if (ed.fieldIno.Name == enumValue.ToString())
                    return ed.EnumDisplayText;
            }
            return string.Empty;
        }


        /// <summary>
        /// 得到枚举类型定义的所有文本,按定义的顺序返回
        /// </summary>
        /// <exception cref="NotSupportedException"></exception>
        /// <param name="enumType">枚举类型</param>
        /// <returns>所有定义的文本</returns>
        public static EnumDescription[] GetFieldTexts(Type enumType)
        {
            return GetFieldTexts(enumType, SortType.Default);
        }

        /// <summary>
        /// 得到枚举类型定义的所有文本
        /// </summary>
        /// <exception cref="NotSupportedException"></exception>
        /// <param name="enumType">枚举类型</param>
        /// <param name="sortType">指定排序类型</param>
        /// <returns>所有定义的文本</returns>
        public static EnumDescription[] GetFieldTexts(Type enumType, SortType sortType)
        {
            EnumDescription[] descriptions = null;
            //缓存中没有找到,通过反射获得字段的描述信息
            if (cachedEnum.Contains(enumType.FullName) == false)
            {
                FieldInfo[] fields = enumType.GetFields();
                ArrayList edAL = new ArrayList();
                foreach (FieldInfo fi in fields)
                {
                    object[] eds = fi.GetCustomAttributes(typeof(EnumDescription), false);
                    if (eds.Length != 1)
                        continue;
                    ((EnumDescription)eds[0]).fieldIno = fi;
                    edAL.Add(eds[0]);
                }

                cachedEnum.Add(enumType.FullName, (EnumDescription[])edAL.ToArray(typeof(EnumDescription)));
            }
            descriptions = (EnumDescription[])cachedEnum[enumType.FullName];
            if (descriptions.Length <= 0)
                throw new NotSupportedException("枚举类型[" + enumType.Name + "]未定义属性EnumValueDescription");

            //按指定的属性冒泡排序
            for (int m = 0; m < descriptions.Length; m++)
            {
                //默认就不排序了
                if (sortType == SortType.Default)
                    break;

                for (int n = m; n < descriptions.Length; n++)
                {
                    EnumDescription temp;
                    bool swap = false;

                    switch (sortType)
                    {
                        case SortType.Default:
                            break;
                        case SortType.DisplayText:
                            if (string.Compare(descriptions[m].EnumDisplayText, descriptions[n].EnumDisplayText) > 0)
                                swap = true;
                            break;
                        case SortType.Rank:
                            if (descriptions[m].EnumRank > descriptions[n].EnumRank)
                                swap = true;
                            break;
                    }
                    if (swap)
                    {
                        temp = descriptions[m];
                        descriptions[m] = descriptions[n];
                        descriptions[n] = temp;
                    }
                }
            }

            return descriptions;
        }
    
        /* 用法 */

        /*

        string txt = EnumDescription.GetEnumText(typeof(OrderStateEnum));    

        string txt = EnumDescription.GetFieldText(OrderStateEnum.Processing); 

        EnumDescription[] des = EnumDescription.GetFieldTexts(typeof(OrderStateEnum)) 

        public static EnumDescription[] GetFieldTexts( Type enumType, SortType sortType )

        */
    }
}

 

CoverWaterImage.cs 代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using System.IO;

namespace ImageWaterMark
{
    public class CoverWaterImage
    {

        private const string waterMarkImagePath = "~/images/waterMark.png"; // 水印图片虚拟路径

        /// <summary>
        /// 给图片加水印
        /// </summary>
        /// <param name="physicalImagePath">需要加水印的图片的物理路径</param>
        /// <param name="savedPhysicalPath">保存后的水印图片的物理路径</param>
        /// <param name="errorMessage">操作失败后显示的错误信息</param>
        /// <param name="imagePosition">水印要加入的地方</param>
        /// <returns>是否成功,true 表示成功</returns>
        public static bool MakeCoverWaterImage(string physicalImagePath, string savedPhysicalPath, out string errorMessage, ImagePosition imagePosition)
        {
            errorMessage = string.Empty;
            if (File.Exists(physicalImagePath))
            {
                //文件存在
                Image coverImage = Image.FromFile(physicalImagePath);
                Image waterMarkImage = Image.FromFile(HttpContext.Current.Server.MapPath(waterMarkImagePath));
                if (coverImage.Width <= (waterMarkImage.Width + 10) || coverImage.Height <= (waterMarkImage.Height + 10))
                {
                    errorMessage = "图片的宽度或高度太小。";
                    waterMarkImage.Dispose();
                    coverImage.Dispose();
                    return false;
                }
                Graphics gh = null;
                try
                {
                    gh = Graphics.FromImage(coverImage);
                }
                catch (Exception)
                {
                    errorMessage = "画布创建失败!";
                    waterMarkImage.Dispose();
                    coverImage.Dispose();
                    return false;
                }
                float x;
                float y;
                float xOffset = 10; //宽度偏移量
                float yOffset = 10; //高度偏移量
                switch (imagePosition)
                {
                    case ImagePosition.Bottom:
                        //正下方
                        x = ((float)coverImage.Width - waterMarkImage.Width) / 2;
                        y = coverImage.Height - waterMarkImage.Height - yOffset;
                        break;
                    case ImagePosition.LeftBottom:
                        //左下方
                        x = xOffset;
                        y = coverImage.Height - waterMarkImage.Height - yOffset;
                        break;
                    case ImagePosition.Right:
                        //右方
                        x = coverImage.Width - waterMarkImage.Width - xOffset;
                        y = ((float)coverImage.Height - waterMarkImage.Height) / 2;
                        break;
                    case ImagePosition.Middle:
                        //正中
                        x = ((float)coverImage.Width - waterMarkImage.Width) / 2;
                        y = ((float)coverImage.Height - waterMarkImage.Height) / 2;
                        break;
                    case ImagePosition.Left:
                        //左边
                        x = xOffset;
                        y = ((float)coverImage.Height - waterMarkImage.Height) / 2;
                        break;
                    case ImagePosition.RightTop:
                        //右上方
                        x = coverImage.Width - waterMarkImage.Width - xOffset;
                        y = yOffset;
                        break;
                    case ImagePosition.Top:
                        //正上方
                        x = ((float)coverImage.Width - waterMarkImage.Width) / 2;
                        y = yOffset;
                        break;
                    case ImagePosition.LeftTop:
                        //左上方
                        x = xOffset;
                        y = yOffset;
                        break;
                    case ImagePosition.Default:
                    case ImagePosition.RightBottom:
                    default:
                        //右下角
                        x = coverImage.Width - waterMarkImage.Width - xOffset;
                        y = coverImage.Height - waterMarkImage.Height - yOffset;
                        break;
                }
                gh.DrawImage(waterMarkImage, x, y, waterMarkImage.Width, waterMarkImage.Height);
                gh.Save();
                gh.Dispose();
                waterMarkImage.Dispose();
                coverImage.Save(savedPhysicalPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                coverImage.Dispose();
            }
            else
            {
                //文件不存在
                return false;
            }
            return true;
        }
    }
}

 

结果效果图:

 

 

 

提交后效果图:

重新裁剪后:

 

 

 

等待更新...

 

 

附件下载:

 

 https://files.cnblogs.com/Music/ImageWaterMark%5bASP.NET%e5%9b%be%e7%89%87%e5%8a%a0%e6%b0%b4%e5%8d%b0%ef%bc%8c%e5%8f%af%e5%8a%a0%e5%9c%a8%e4%bb%bb%e6%84%8f%e5%9c%b0%e6%96%b9%5d.rar

 

 

欢迎您的评论! o(∩_∩)o