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類文件

 

    希望有所幫助~ 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM