ASP.NET为图片添加水印功能示例详解


    这两天主要在学习如何给图片添加水印,查找了一下相关的解决方案,其中有一个别人写好的水印dll,虽然能实现很多的功能,但很遗憾不能用于其他商业用途,没办法只能再找找别的办法,后面找到的这种方法比较简单,就是通过Graphics重新绘制bitmap的方法来绘制水印,当然,文字水印可能稍微要麻烦一点儿,需要设置字体相关的东东,比如字号、阴影、颜色啥的,但整体来看,思路基本是一样的。

 

    至于具体的步骤说明,请查看源码上的注释即可,应该能够保证大家不至于太迷糊:

 

    第一部分:水印相关参数结构体和枚举

 

    View Code

 
  1          ///   <summary>
  2           ///  水印位置枚举
  3           ///   </summary>
  4           public  enum ImagePosition
  5         {
  6             LeftTop,  // 左上 
  7              LeftBottom,  // 左下 
  8              RightTop,  // 右上 
  9              RigthBottom,  // 右下 
 10              TopMiddle,  // 顶部居中 
 11              BottomMiddle,  // 底部居中 
 12              Center  // 中心 
 13          }
 14 
 15          ///   <summary>
 16           ///  图片水印参数结构体
 17           ///   </summary>
 18           public  struct ImageWatermarkParameters
 19         {
 20              ///   <summary>
 21               ///  源图片路径
 22               ///   </summary>
 23               public  string SourceImagePath;
 24              ///   <summary>
 25               ///  水印图片路径
 26               ///   </summary>
 27               public  string WatermarkImagePath;
 28              ///   <summary>
 29               ///  源图片数据流(即如果设置数据流,则忽略SourceImagePath属性值)
 30               ///   </summary>
 31               public MemoryStream SourceImageStream;
 32              ///   <summary>
 33               ///  水印图片数据流(即如果设置数据流,则忽略WatermarkImagePath属性值)
 34               ///   </summary>
 35               public MemoryStream WatermarkImageStream;
 36              ///   <summary>
 37               ///  透明度,数值介于0.1 - 1.0之间,不包括0.0
 38               ///   </summary>
 39               public  float Alpha;
 40              ///   <summary>
 41               ///  水印位置
 42               ///   </summary>
 43               public ImagePosition WmPosition;
 44              private  string _sourceImageFileExtensionName;
 45              ///   <summary>
 46               ///  源图片文件扩展名
 47               ///   </summary>
 48               public  string SourceImageFileExtensionName
 49             {
 50                  set { _sourceImageFileExtensionName = value; }
 51                  get
 52                 {
 53                      if ( string.IsNullOrEmpty( this.SourceImagePath))
 54                     {
 55                          //  如果设置的图片扩展名为ContentType类型,则进行转化
 56                           if (_sourceImageFileExtensionName.IndexOf( " / ") >  0)
 57                             _sourceImageFileExtensionName = TransferContentTypeToUnifyExName(_sourceImageFileExtensionName);
 58 
 59                          return _sourceImageFileExtensionName;
 60                     }
 61                      else
 62                          return Path.GetExtension(SourceImagePath).ToLower();
 63                 }
 64             }
 65 
 66 
 67              public ImageWatermarkParameters( string sourceImagePath,  string watermarkImagePath,  float alpha, ImagePosition wmPosition)
 68             {
 69                  this.SourceImageStream =  null;
 70                  this.WatermarkImageStream =  null;
 71                  this._sourceImageFileExtensionName =  string.Empty;
 72 
 73                  this.SourceImagePath = sourceImagePath;
 74                  this.WatermarkImagePath = watermarkImagePath;
 75                  this.Alpha = alpha;
 76                  this.WmPosition = wmPosition;
 77             }
 78 
 79              public ImageWatermarkParameters(MemoryStream sourceImageStream, MemoryStream watermarkImageStream, 
 80                  string sourceImageFileExtensionName,  float alpha, ImagePosition wmPosition)
 81             {
 82                  this.SourceImagePath =  string.Empty;
 83                  this.WatermarkImagePath =  string.Empty; ;
 84 
 85                  this.SourceImageStream = sourceImageStream;
 86                  this.WatermarkImageStream = watermarkImageStream;
 87                  this.Alpha = alpha;
 88                  this.WmPosition = wmPosition;
 89                  this._sourceImageFileExtensionName = sourceImageFileExtensionName;
 90             }
 91 
 92              ///   <summary>
 93               ///  参数检查并设定默认值
 94               ///   </summary>
 95               ///   <param name="errorMsg"></param>
 96               ///   <returns></returns>
 97               public  bool CheckAndSetDefault( out  string errorMsg)
 98             {
 99                 errorMsg =  string.Empty;
100 
101                  //  前置检查
102                   if (( string.IsNullOrEmpty( this.SourceImagePath) && SourceImageStream ==  null)
103                     || ( string.IsNullOrEmpty( this.WatermarkImagePath) && WatermarkImageStream ==  null)
104                     || (SourceImageStream !=  null &&  string.IsNullOrEmpty(_sourceImageFileExtensionName))
105                     ||  this.Alpha <=  0.0 ||  this.Alpha >  1.0
106                     ||  this.WmPosition ==  null)
107                 {
108                     errorMsg =  " 文字水印参数实体中含有非法的参数项。 ";
109                      return  false;
110                 }
111 
112                  //  检查图片路径是否合法
113                   if ((SourceImageStream ==  null && ! string.IsNullOrEmpty( this.SourceImagePath) && !File.Exists( this.SourceImagePath))  //  仅赋值源图片路径,且路径不存在的情况
114                      || (WatermarkImageStream ==  null && ! string.IsNullOrEmpty( this.WatermarkImagePath) && !File.Exists( this.WatermarkImagePath)))  //  仅赋值水印图片路径,但文件不存在的情况
115                  {
116                     errorMsg =  " 输入的源图片或水印图片路径不存在。 ";
117                      return  false;
118                 }
119 
120 
121                  //  检查图片扩展名
122                   bool validExName =  true;
123                  if (! string.IsNullOrEmpty( this.SourceImagePath) && ! string.IsNullOrEmpty( this.WatermarkImagePath))
124                 {
125                      if (!CheckImageExtensionType( this.SourceImagePath) || !CheckImageExtensionType( this.WatermarkImagePath))
126                         validExName =  false;
127                 }
128                  else  if ( this.SourceImageStream !=  null &&  this.WatermarkImageStream !=  null)
129                 {
130                      if ((_sourceImageFileExtensionName !=  " .gif " && _sourceImageFileExtensionName !=  " .jpg " && _sourceImageFileExtensionName !=  " .png "))
131                         validExName =  false;
132                 }
133                  else
134                     validExName =  false;
135 
136                  if (!validExName)
137                 {
138                     errorMsg =  " 暂不支持源图片或水印图片的格式类型。 ";
139                      return  false;
140                 }
141 
142                  return  true;
143             }
144         }
145 
146          ///   <summary>
147           ///  文字水印参数结构体
148           ///   </summary>
149           public  struct TextWatermarkParameters
150         {
151              ///   <summary>
152               ///  源图片路径
153               ///   </summary>
154               public  string SourceImagePath;
155              ///   <summary>
156               ///  水印文字
157               ///   </summary>
158               public  string WatermarkText;
159              ///   <summary>
160               ///  源图片数据流
161               ///   </summary>
162               public MemoryStream SourceImageStream;
163              ///   <summary>
164               ///  透明度,数值介于0.1 - 1.0之间,不包括0.0
165               ///   </summary>
166               public  float Alpha;
167              ///   <summary>
168               ///  水印位置
169               ///   </summary>
170               public ImagePosition WmPosition;
171              ///   <summary>
172               ///  水印文字字体样式
173               ///   </summary>
174               public Font WmTextFont;
175              ///   <summary>
176               ///  水印文字阴影宽度
177               ///   </summary>
178               public  int TextShadowWidth;
179              private  string _sourceImageFileExtensionName;
180              ///   <summary>
181               ///  源图片文件扩展名
182               ///   </summary>
183               public  string SourceImageFileExtensionName
184             {
185                  set { _sourceImageFileExtensionName = value; }
186                  get
187                 {
188                      if ( string.IsNullOrEmpty( this.SourceImagePath))
189                     {
190                          //  如果设置的图片扩展名为ContentType类型,则进行转化
191                           if (_sourceImageFileExtensionName.IndexOf( " / ") >  0)
192                             _sourceImageFileExtensionName = TransferContentTypeToUnifyExName(_sourceImageFileExtensionName);
193 
194                          return _sourceImageFileExtensionName;
195                     }
196                      else
197                          return Path.GetExtension(SourceImagePath).ToLower();
198                 }
199             }
200 
201 
202              public TextWatermarkParameters(MemoryStream sourceImageStream,  string sourceImageFileExtensionName,  string watermarkText,  float alpha, 
203                 ImagePosition wmPosition, Font wmTextFont,  int textShadowWidth =  5)
204             {
205                  this.SourceImagePath =  string.Empty ;
206 
207                  this.SourceImageStream = sourceImageStream;
208                  this.WatermarkText = watermarkText;
209                  this.Alpha = alpha;
210                  this.WmPosition = wmPosition;
211                  this.WmTextFont = wmTextFont;
212                  this.TextShadowWidth = textShadowWidth;
213                  this._sourceImageFileExtensionName = sourceImageFileExtensionName;
214             }
215 
216              public TextWatermarkParameters( string sourceImagePath,  string watermarkText,  float alpha,
217                 ImagePosition wmPosition, Font wmTextFont,  int textShadowWidth =  5)
218             {
219                  this.SourceImageStream =  null;
220                  this._sourceImageFileExtensionName =  string.Empty;
221 
222                  this.SourceImagePath = sourceImagePath;
223                  this.WatermarkText = watermarkText;
224                  this.Alpha = alpha;
225                  this.WmPosition = wmPosition;
226                  this.WmTextFont = wmTextFont;
227                  this.TextShadowWidth = textShadowWidth;
228             }
229 
230              ///   <summary>
231               ///  参数检查并设定默认值
232               ///   </summary>
233               ///   <param name="errorMsg"></param>
234               ///   <returns></returns>
235               public  bool CheckAndSetDefault( out  string errorMsg)
236             {
237                 errorMsg =  string.Empty;
238 
239                  //  前置检查
240                   if (( string.IsNullOrEmpty( this.SourceImagePath) &&  this.SourceImageStream ==  null) || (! string.IsNullOrEmpty( this.SourceImagePath) && !File.Exists( this.SourceImagePath)) 
241                     ||  string.IsNullOrEmpty( this.WatermarkText)
242                     || (SourceImageStream !=  null &&  string.IsNullOrEmpty(_sourceImageFileExtensionName))
243                     ||  this.Alpha <=  0.0 ||  this.Alpha >  1.0
244                     ||  this.WmPosition ==  null
245                     ||  this.WmTextFont ==  null)
246                 {
247                     errorMsg =  " 文字水印参数实体中含有非法的参数项。 ";
248                      return  false;
249                 }
250 
251                  //  检查图片路径是否合法
252                   if ((SourceImageStream ==  null && ! string.IsNullOrEmpty( this.SourceImagePath) && !File.Exists( this.SourceImagePath)))  //  仅赋值源图片路径,且路径不存在的情况
253                  {
254                     errorMsg =  " 输入的源图片路径不存在。 ";
255                      return  false;
256                 }
257 
258                  //  检查图片扩展名
259                   bool validExName =  true;
260                  if (! string.IsNullOrEmpty( this.SourceImagePath))
261                 {
262                      if (!CheckImageExtensionType( this.SourceImagePath))
263                         validExName =  false;
264                 }
265                  else  if ( this.SourceImageStream !=  null)
266                 {
267                      if ((_sourceImageFileExtensionName !=  " .gif " && _sourceImageFileExtensionName !=  " .jpg " && _sourceImageFileExtensionName !=  " .png "))
268                         validExName =  false;
269                 }
270                  else
271                     validExName =  false;
272 
273                  if (!validExName)
274                 {
275                     errorMsg =  " 暂不支持源图片的格式类型。 ";
276                      return  false;
277                 }
278 
279                  return  true;
280             }
281

 

    第二部分:水印功能处理类 -> 内部辅助函数部分

 

    View Code

 
         ///   <summary>
        
///  获取编码参数数组
        
///   </summary>
        
///   <returns></returns>
         private  static EncoderParameters GetEncoderParameters()
        {
            EncoderParameters eps =  new EncoderParameters( 1);
            EncoderParameter ep =  new EncoderParameter(Encoder.Quality, _imageSaveQualityValue);
            eps.Param[ 0] = ep;

             return eps;
        }

         ///   <summary>
        
///  根据图片格式获取编码信息
        
///   </summary>
        
///   <param name="mimeType"> 图片格式 </param>
        
///   <returns> 编码信息 </returns>
         private  static ImageCodecInfo GetEncoderInfo(String mimeType)
        {
             int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
             for (j =  0; j < encoders.Length; ++j)
            {
                 if (encoders[j].MimeType == mimeType)
                     return encoders[j];
            }
             return  null;
        }

         ///   <summary>
        
///  获取最终图片保存的图像格式
        
///   </summary>
        
///   <param name="imageExtensionName"> 图片扩展名称 </param>
        
///   <returns> 图片格式 </returns>
         private  static ImageCodecInfo GetFinalImageCodecInfo( string imageExtensionName)
        {
             switch (imageExtensionName)
            { 
                 case  " .gif ":
                     return GetEncoderInfo( " image/gif ");
                 case  " .png ":
                     return GetEncoderInfo( " image/png ");
                 case  " .jpg ":
                 default:
                     return GetEncoderInfo( " image/jpeg ");
            }
        }

         ///   <summary>
        
///  获取文字画刷
        
///   </summary>
        
///   <param name="alpha"> 透明度 </param>
        
///   <returns></returns>
         private  static SolidBrush GetTextBrush( float alpha)
        {
             //  从四个 ARGB 分量(alpha、红色、绿色和蓝色)值创建 Color 结构,这里设置透明度为153 
            
//  这个画笔为描绘正式文字的笔刷,呈白色 
            SolidBrush semiTransBrush =  new SolidBrush(Color.FromArgb(Convert.ToInt32( 255 * alpha), Color.White));
             return semiTransBrush;
        }

         ///   <summary>
        
///  获取阴影画刷
        
///   </summary>
        
///   <returns></returns>
         private  static SolidBrush GetShadowBrush()
        {
             //  SolidBrush:定义单色画笔。画笔用于填充图形形状,如矩形、椭圆、扇形、多边形和封闭路径。 
            
//  这个画笔为描绘阴影的画笔,呈灰色
             return  new SolidBrush(Color.FromArgb( 153, Color.Blue));
        }

         ///   <summary>
        
///  获取文本布局信息
        
///   </summary>
        
///   <returns></returns>
         private  static StringFormat GetStringFormat()
        {
             //  封装文本布局信息(如对齐、文字方向和 Tab 停靠位),显示操作(如省略号插入和国家标准 (National) 数字替换)和 OpenType 功能
            StringFormat StrFormat =  new StringFormat();
            StrFormat.Alignment = StringAlignment.Center;

             return StrFormat;
        }

         ///   <summary>
        
///  Get image attribute instance.
        
///   </summary>
        
///   <param name="alpha"> transparency value </param>
        
///   <returns></returns>
         private  static ImageAttributes GetImageAttributesInstance( float alpha)
        {
             //  imageattributes instance which will control the related infomations for image.
            ImageAttributes imageAttributes =  new ImageAttributes();

             //  图片映射:水印图被定义成拥有绿色背景色的图片被替换成透明 
            ColorMap colorMap =  new ColorMap();
            colorMap.OldColor = Color.FromArgb( 25502550);
            colorMap.NewColor = Color.FromArgb( 0000);
            imageAttributes.SetRemapTable( new ColorMap[] { colorMap }, ColorAdjustType.Bitmap);

             float[][] colorMatrixElements =  new  float[][] 
            { 
                 new  float[] { 1.0f0.0f0.0f0.0f0.0f},  //  red红色 
                 new  float[] { 0.0f1.0f0.0f0.0f0.0f},  //  green绿色 
                 new  float[] { 0.0f0.0f1.0f0.0f0.0f},  //  blue蓝色 
                 new  float[] { 0.0f0.0f0.0f, alpha,  0.0f},  //  透明度 
                 new  float[] { 0.0f0.0f0.0f0.0f1.0f}
            };

             //  ColorMatrix:定义包含 RGBA 空间坐标的 5 x 5 矩阵。 
            
//  ImageAttributes:类的若干方法通过使用颜色矩阵调整图像颜色。 
            imageAttributes.SetColorMatrix( new ColorMatrix(colorMatrixElements), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

             return imageAttributes;
        }

         ///   <summary>
        
///  Calculate the watermark image position.
        
///   </summary>
        
///   <param name="position"> position </param>
        
///   <param name="srcWidth"> source image width </param>
        
///   <param name="srcHeight"> source image height </param>
        
///   <param name="wmWidth"> watermark image width </param>
        
///   <param name="wmHeight"> watermark image height </param>
        
///   <param name="xPosOfWm"> final x position </param>
        
///   <param name="yPosOfWm"> final y position </param>
         private  static  void GetWatermarkImagePosition(ImagePosition position,  int srcWidth,  int srcHeight,  int wmWidth,  int wmHeight,  out  int xPosOfWm,  out  int yPosOfWm)
        {
             switch (position)
            {
                 case ImagePosition.BottomMiddle:
                    xPosOfWm = (srcWidth - wmWidth) /  2;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.Center:
                    xPosOfWm = (srcWidth - wmWidth) /  2;
                    yPosOfWm = (srcHeight - wmHeight) /  2;
                     break;
                 case ImagePosition.LeftBottom:
                    xPosOfWm =  10;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.LeftTop:
                    xPosOfWm =  10;
                    yPosOfWm =  10;
                     break;
                 case ImagePosition.RightTop:
                    xPosOfWm = srcWidth - wmWidth -  10;
                    yPosOfWm =  10;
                     break;
                 case ImagePosition.RigthBottom:
                    xPosOfWm = srcWidth - wmWidth -  10;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.TopMiddle:
                    xPosOfWm = (srcWidth - wmWidth) /  2;
                    yPosOfWm =  10;
                     break;
                 default:
                    xPosOfWm =  10;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
            }
        }

         ///   <summary>
        
///  Calculate the watermark image position.
        
///   </summary>
        
///   <param name="position"> position </param>
        
///   <param name="srcWidth"> source image width </param>
        
///   <param name="srcHeight"> source image height </param>
        
///   <param name="wmWidth"> watermark image width </param>
        
///   <param name="wmHeight"> watermark image height </param>
        
///   <param name="xPosOfWm"> final x position </param>
        
///   <param name="yPosOfWm"> final y position </param>
         private  static  void GetWatermarkTextPosition(ImagePosition position,  int srcWidth,  int srcHeight,  float wmWidth,  float wmHeight,  out  float xPosOfWm,  out  float yPosOfWm)
        {
             switch (position)
            {
                 case ImagePosition.BottomMiddle:
                    xPosOfWm = srcWidth /  2;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.Center:
                    xPosOfWm = srcWidth /  2;
                    yPosOfWm = srcHeight /  2;
                     break;
                 case ImagePosition.LeftBottom:
                    xPosOfWm = wmWidth;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.LeftTop:
                    xPosOfWm = wmWidth /  2;
                    yPosOfWm = wmHeight /  2;
                     break;
                 case ImagePosition.RightTop:
                    xPosOfWm = srcWidth - wmWidth -  10;
                    yPosOfWm = wmHeight;
                     break;
                 case ImagePosition.RigthBottom:
                    xPosOfWm = srcWidth - wmWidth -  10;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
                 case ImagePosition.TopMiddle:
                    xPosOfWm = srcWidth /  2;
                    yPosOfWm = wmWidth;
                     break;
                 default:
                    xPosOfWm = wmWidth;
                    yPosOfWm = srcHeight - wmHeight -  10;
                     break;
            }
        }

         ///   <summary>
        
///  Check image extension type.
        
///   </summary>
        
///   <param name="sourceImagePath"> image path </param>
        
///   <returns> examine result </returns>
         private  static  bool CheckImageExtensionType( string imagePath)
        {
             string fileExtensionType = System.IO.Path.GetExtension(imagePath).ToLower();
             return (System.IO.File.Exists(imagePath) && (fileExtensionType ==  " .gif " || fileExtensionType ==  " .jpg " || fileExtensionType ==  " .png "));
        }

         ///   <summary>
        
///  获取Bitmap的MemoryStream
        
///   </summary>
        
///   <param name="finalImage"></param>
        
///   <returns></returns>
         private  static MemoryStream GetMemoryStreamFromBitmap(Bitmap finalImage,  string sourceImageFileExName)
        {
            MemoryStream ms =  new MemoryStream();
             //  将位图保存到数据流中
            finalImage.Save(ms, GetFinalImageCodecInfo(sourceImageFileExName), GetEncoderParameters());
             return ms;
        }

         ///   <summary>
        
///  获取源图片和水印图片的数据流
        
///   </summary>
        
///   <param name="parameters"> 参数实例 </param>
        
///   <param name="sourceImageStream"> 源图片数据流 </param>
        
///   <param name="waterImageStream"> 水印图片数据流 </param>
        
///   <param name="errorMsg"> 错误信息 </param>
        
///   <returns> 是否获取成功 </returns>
         private  static  bool GetSourceAndWatermarkImageStream(ImageWatermarkParameters parameters,
             out MemoryStream sourceImageStream,  out MemoryStream waterImageStream,  out  string errorMsg)
        {
            errorMsg =  string.Empty;

             //  根据是否设置图片路径来判断如何获取图片数据流,分别获取源图片和水印图片的数据流。
             string scErrMsg =  string.Empty, wmErrMsg =  string.Empty;
            sourceImageStream = parameters.SourceImageStream ==  null ?
                GetImageMemoryStream(parameters.SourceImagePath,  out scErrMsg) : parameters.SourceImageStream;

            waterImageStream = parameters.WatermarkImageStream ==  null ?
                GetImageMemoryStream(parameters.WatermarkImagePath,  out wmErrMsg) : parameters.WatermarkImageStream;

             if (! string.IsNullOrEmpty(scErrMsg) || ! string.IsNullOrEmpty(wmErrMsg))
            {
                errorMsg =  " 通过图片路径获取数据流失败: " + scErrMsg +  " " + wmErrMsg;
                 return  false;
            }

             return  true;
        }

         ///   <summary>
        
///  判断图片的PixelFormat 是否在 引发异常的 PixelFormat 之中
        
///   </summary>
        
///   <param name="imgPixelFormat"> 原图片的PixelFormat </param>
        
///   <returns></returns>
         private  static  bool IsPixelFormatIndexed(PixelFormat imgPixelFormat)
        {
            PixelFormat[] indexedPixelFormats = { 
                PixelFormat.Undefined, 
                PixelFormat.DontCare,
                PixelFormat.Format16bppArgb1555, 
                PixelFormat.Format1bppIndexed, 
                PixelFormat.Format4bppIndexed,
                PixelFormat.Format8bppIndexed
            };

             //  遍历匹配
             foreach (PixelFormat pf  in indexedPixelFormats)
                 if (pf.Equals(imgPixelFormat))
                     return  true;

             return  false;
        }

         ///   <summary>
        
///  将原图未索引像素格式之类的Image转化为Bitmap
        
///   </summary>
        
///   <param name="image"> 图像实体 </param>
        
///   <returns> 位图实体 </returns>
         private  static Bitmap RedrawBitmapByImage(Image image) 
        {
            Bitmap bmp =  new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
             using (Graphics g = Graphics.FromImage(bmp))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.DrawImage(image,  00);
            }

             return bmp;
        }

         ///   <summary>
        
///  保证得到内部统一使用的文件扩展格式
        
///   </summary>
        
///   <param name="extensionName"></param>
        
///   <returns></returns>
         private  static  string TransferContentTypeToUnifyExName( string contentType)
        {
             string exName =  string.Empty;
             switch (contentType.ToLower())
            {
                 case  " image/jpeg ":
                 case  " image/pjpeg ":
                    exName =  " .jpg ";
                     break;
                 case  " image/gif ":
                    exName =  " .gif ";
                     break;
                 case  " image/x-png ":
                 case  " image/png ":
                    exName =  " .png ";
                     break;
                 default:
                    exName = contentType;
                     break;
            }

             return exName;

 

    第三部分:水印功能处理类 -> 主体处理函数部分

 

    View Code

 
         #region 添加水印功能主体函数

         ///   <summary>
        
///  为图片添加文字水印
        
///   </summary>
        
///   <param name="parameters"> 文字水印相关参数体 </param>
        
///   <param name="errMsg"> 错误信息 </param>
        
///   <returns> 添加完水印的位图对象 </returns>
         private  static Bitmap AddWatermarkTextForSourceImage(TextWatermarkParameters parameters,  out  string errMsg)
        {
            Image srcImage =  null;
            Graphics srcGraphics =  null;
            errMsg =  string.Empty;

             try
            {
                 //
                
//  获取源图片数据流
                MemoryStream scMs = parameters.SourceImageStream ==  null ?
                    GetImageMemoryStream(parameters.SourceImagePath,  out errMsg) : parameters.SourceImageStream;
                 if (scMs ==  null && ! string.IsNullOrEmpty(errMsg))
                     throw  new InvalidDataException( " 获取图片数据流失败! ");

                 //
                
//
                srcImage = Image.FromStream(scMs  as Stream);
                 //  新建位图并设定分辨率,需要根据图像的像素格式来判断是否需要重新绘制该图像
                Bitmap srcBitmap = (IsPixelFormatIndexed(srcImage.PixelFormat)) ? 
                    RedrawBitmapByImage(srcImage) : 
                     new Bitmap(srcImage.Width, srcImage.Height, srcImage.PixelFormat);
                srcBitmap.SetResolution(srcImage.HorizontalResolution, srcImage.VerticalResolution);
                 //  封装一个GDI+绘图图面,并设置图形品质
                srcGraphics = Graphics.FromImage(srcBitmap);
                srcGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                 //  向源图片绘制到位图中
                srcGraphics.DrawImage(srcImage,  new Rectangle( 00, srcImage.Width, srcImage.Height),  00, srcImage.Width, srcImage.Height, GraphicsUnit.Pixel);


                 //
                
//  矩形的宽度和高度,SizeF有三个属性,分别为Height高,width宽,IsEmpty是否为空 
                SizeF crSize = srcGraphics.MeasureString(parameters.WatermarkText, parameters.WmTextFont);
                 //  获取水印文字的起始位置
                 float xPosOfWm, yPosOfWm =  0;
                GetWatermarkTextPosition(parameters.WmPosition, srcImage.Width, srcImage.Height, crSize.Width, crSize.Height,  out xPosOfWm,  out yPosOfWm);

                 //
                
//  文本样式
                StringFormat vmTextFormat = GetStringFormat();
                 //  阴影画刷
                SolidBrush shadowBrush = GetShadowBrush();
                 //  文字画刷
                SolidBrush semiTransBrush = GetTextBrush(parameters.Alpha);
                 //  第一步,绘制阴影
                srcGraphics.DrawString(parameters.WatermarkText, parameters.WmTextFont, shadowBrush,
                     new PointF(xPosOfWm + parameters.TextShadowWidth, yPosOfWm + parameters.TextShadowWidth), vmTextFormat);
                 //  第二步,绘制文字
                srcGraphics.DrawString(parameters.WatermarkText, parameters.WmTextFont, semiTransBrush,  new PointF(xPosOfWm, yPosOfWm), vmTextFormat);

                 return srcBitmap;
            }
             catch (Exception e)
            {
                errMsg = e.Message.ToString();
                 return  null;
            }
             finally
            {  //  释放资源
                 if (srcImage !=  null)
                    srcImage.Dispose();
                 if (srcGraphics !=  null)
                    srcGraphics.Dispose();
            }
        }

         ///   <summary>
        
///  为源图片添加图片水印
        
///   </summary>
        
///   <param name="parameters"> 参数集合 </param>
        
///   <param name="errMsg"> 错误消息 </param>
        
///   <returns> 添加完水印的位图对象 </returns>
         private  static Bitmap AddWatermarkImageForSourceImage(ImageWatermarkParameters parameters,  out  string errMsg)
        {
            Image sourceImage =  null;
            Bitmap sourceBitmap =  null;
            Graphics sourceGraphics =  null;
            Image watermarkImage =  null;
            Graphics watermarkGraphics =  null;
            errMsg =  string.Empty;

             try
            {
                 //  获取源图片和水印图片的数据流
                MemoryStream sourceImageStream, waterImageStream =  null;
                 if (GetSourceAndWatermarkImageStream(parameters,  out sourceImageStream,  out waterImageStream,  out errMsg) ==  false)
                     throw  new InvalidDataException(errMsg);


                sourceImage = Image.FromStream(sourceImageStream  as Stream);
                 //  实例化一个与源图大小一样、分辨率一致的位图对象,并将其载入Graphics对象中,以便后续编辑;
                
//  需要根据图像的像素格式来判断是否需要重新绘制该图像
                sourceBitmap = (IsPixelFormatIndexed(sourceImage.PixelFormat)) ?
                    RedrawBitmapByImage(sourceImage) :
                     new Bitmap(sourceImage.Width, sourceImage.Height, sourceImage.PixelFormat);
                sourceBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                sourceGraphics = Graphics.FromImage(sourceBitmap);

                 //  SmoothingMode:指定是否将平滑处理(消除锯齿)应用于直线、曲线和已填充区域的边缘。 
                
//  成员名称 说明 
                
//  AntiAlias 指定消除锯齿的呈现。 
                
//  Default 指定不消除锯齿。 
                
//  HighQuality 指定高质量、低速度呈现。 
                
//  HighSpeed 指定高速度、低质量呈现。 
                
//  Invalid 指定一个无效模式。 
                
//  None 指定不消除锯齿。 
                sourceGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                 //  将源图像Image对象添加到绘图板中
                sourceGraphics.DrawImage(sourceImage,  new Rectangle( 00, sourceImage.Width, sourceImage.Height),
                                             00, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel);


                 //
                
//  按照源图片的操作方式,需要创建水印图片的Image对象、位图对象,
                
//  只是需要根据输入参数来调整水印图片在源图片中的位置、显示效果等。
                watermarkImage =  new Bitmap(waterImageStream);
                 //  这里尤其注意,生成新位图的时候,载入的是已经添加了源图片作为背景的位图哦!
                
//  并将设定好分辨率的位图载入到新的Graphics实例中,以进一步绘制水印。
                Bitmap watermarkBitmap =  new Bitmap(sourceBitmap);
                watermarkBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                watermarkGraphics = Graphics.FromImage(watermarkBitmap);

                 //  通过imageAttributes实例来设定水印图片的绘制效果,包括位置和现实效果等
                ImageAttributes imageAttributes = GetImageAttributesInstance(parameters.Alpha);
                 //  获取水印图片的起始位置
                 int xPosOfWm, yPosOfWm =  0;
                GetWatermarkImagePosition(parameters.WmPosition, sourceImage.Width, sourceImage.Height, watermarkImage.Width, watermarkImage.Height,  out xPosOfWm,  out yPosOfWm);
                 //  绘制水印图片
                watermarkGraphics.DrawImage(watermarkImage,  new Rectangle(xPosOfWm, yPosOfWm, watermarkImage.Width, watermarkImage.Height),
                                                 00, watermarkImage.Width, watermarkImage.Height, GraphicsUnit.Pixel, imageAttributes);

                 return watermarkBitmap;
            }
             catch (Exception e)
            {
                errMsg = e.Message.ToString();
                 return  null;
            }
             finally
            {
                 //  释放
                 if (sourceImage !=  null)
                    sourceImage.Dispose();
                 if (sourceBitmap !=  null)
                    sourceBitmap.Dispose();
                 if (sourceGraphics !=  null)
                    sourceGraphics.Dispose();
                 if (watermarkImage !=  null)
                    watermarkImage.Dispose();
                 if (watermarkGraphics !=  null)
                    watermarkGraphics.Dispose();
            }
        }

        

 

    第四部分:水印功能处理类 -> 对外公开方法(即调用方法)

 

    View Code

 
         #region 主要公开方法

         ///   <summary>
        
///  图片保存质量值
        
///   </summary>
         private  static  int _imageSaveQualityValue =  100;


         ///   <summary>
        
///  为图片添加图片水印
        
///   </summary>
        
///   <param name="parameters"> 添加图片水印相关参数体 </param>
        
///   <param name="errorMsg"> 错误信息 </param>
        
///   <returns> 已加水印的图片数据流 </returns>
         public  static MemoryStream DrawImage(ImageWatermarkParameters parameters,  out  string errorMsg)
        {
            errorMsg =  string.Empty;

             try
            {
                 //  参数检查
                 if (!parameters.CheckAndSetDefault( out errorMsg))
                     throw  new InvalidDataException(errorMsg);

                 //  为源图片添加图片水印
                Bitmap finalImage = AddWatermarkImageForSourceImage(parameters,  out errorMsg);
                 if (finalImage ==  null && ! string.IsNullOrEmpty(errorMsg))
                     throw  new InvalidDataException( " 生成水印图片失败: " + errorMsg);

                 //  获取Bitmap的MemoryStream
                 return GetMemoryStreamFromBitmap(finalImage, parameters.SourceImageFileExtensionName);
            }
             catch (Exception ex)
            {
                errorMsg = ex.Message.ToString();
                 return  null;
            }
        }

         ///   <summary>
        
///  为图片添加文字水印
        
///   </summary>
        
///   <param name="parameters"> 文字水印过程需要的参数体 </param>
        
///   <param name="errorMsg"> 异常信息 </param>
        
///   <returns> 已加水印的图片数据流 </returns>
         public  static MemoryStream DrawText(TextWatermarkParameters parameters,  out  string errorMsg)
        {
            errorMsg =  string.Empty;

             try
            {
                 //  参数检查
                 if (!parameters.CheckAndSetDefault( out errorMsg))
                     throw  new InvalidDataException(errorMsg);

                 //  为源图片添加文字水印
                Bitmap finalImage = AddWatermarkTextForSourceImage(parameters,  out errorMsg);
                 if (finalImage ==  null && ! string.IsNullOrEmpty(errorMsg))
                     throw  new InvalidDataException( " 生成水印图片失败: " + errorMsg);

                 return GetMemoryStreamFromBitmap(finalImage, parameters.SourceImageFileExtensionName);
            }
             catch (Exception ex)
            {
                errorMsg = ex.Message.ToString();
                 return  null;
            }
        }

         ///   <summary>
        
///  根据文件路径获取图片数据流
        
///   </summary>
        
///   <param name="filePath"></param>
        
///   <returns></returns>
         private  static MemoryStream GetImageMemoryStream( string filePath,  out  string errorMsg)
        {
            MemoryStream ms =  null;
            errorMsg =  string.Empty;

             try
            {
                 using (FileStream fs = File.OpenRead(filePath))
                {  //  读取图片数据流
                     byte[] buffer =  new  byte[fs.Length];
                    fs.Read(buffer,  0, buffer.Length);
                    ms.Write(buffer,  0, buffer.Length);
                }

                 return ms;
            }
             catch (Exception e)
            {
                errorMsg = e.Message.ToString();
                 return  null;
            }
        }

        

  

    第五部分:添加水印功能调用示例

 

    View Code

 
             string errorMsg =  string.Empty;
             string origenalImagePath =  " D:\\sourcePicture.jpg ";
             float alpha =  0.5F;

             //  图片水印

             string waterPicturePath =  " D:\\watermarkPicture.jpg ";
            WatermarkImageManager.ImageWatermarkParameters image_parameters =
                 new WatermarkImageManager.ImageWatermarkParameters(FileToStream(origenalImagePath), FileToStream(waterPicturePath),  " .jpg ", alpha, WatermarkImageManager.ImagePosition.LeftBottom);
            MemoryStream wmImageMS = WatermarkImageManager.DrawImage(image_parameters,  out errorMsg);

             //  文字水印
             string wmText =  " 水印文字 ";
            Font font =  new Font( " arial "30, FontStyle.Bold);

            WatermarkImageManager.TextWatermarkParameters text_parameters =
                 new WatermarkImageManager.TextWatermarkParameters(FileToStream(origenalImagePath),  " .jpg ", wmText, alpha, WatermarkImageManager.ImagePosition.Center, font);
            MemoryStream wmTextMS = WatermarkImageManager.DrawText(text_parameters,  out

 

    最后把该水印处理类的代码文件附上,方便大家调整,同时支持,传入MemoryStream或输入文件路径两种形式的数据,详情请看参数结构类部分。

 

    点击下载WatermarkImageManager.cs类文件

 

    希望有所帮助~ 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值