ASP.NET 图片加水印,水印位置自定义
2010-09-02 19:40 音乐让我说 阅读(1239) 评论(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; } } }
结果效果图:
提交后效果图:
重新裁剪后:
等待更新...
附件下载:
欢迎您的评论! o(∩_∩)o
作者:音乐让我说(音乐让我说 - 博客园)
出处:http://music.cnblogs.com/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。