這兩天主要在學習如何給圖片添加水印,查找了一下相關的解決方案,其中有一個別人寫好的水印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
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( 255, 0, 255, 0);
colorMap.NewColor = Color.FromArgb( 0, 0, 0, 0);
imageAttributes.SetRemapTable( new ColorMap[] { colorMap }, ColorAdjustType.Bitmap);
float[][] colorMatrixElements = new float[][]
{
new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // red紅色
new float[] { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, // green綠色
new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, // blue藍色
new float[] { 0.0f, 0.0f, 0.0f, alpha, 0.0f}, // 透明度
new float[] { 0.0f, 0.0f, 0.0f, 0.0f, 1.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, 0, 0);
}
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;
/// 獲取編碼參數數組
/// </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( 255, 0, 255, 0);
colorMap.NewColor = Color.FromArgb( 0, 0, 0, 0);
imageAttributes.SetRemapTable( new ColorMap[] { colorMap }, ColorAdjustType.Bitmap);
float[][] colorMatrixElements = new float[][]
{
new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // red紅色
new float[] { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, // green綠色
new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, // blue藍色
new float[] { 0.0f, 0.0f, 0.0f, alpha, 0.0f}, // 透明度
new float[] { 0.0f, 0.0f, 0.0f, 0.0f, 1.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, 0, 0);
}
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( 0, 0, srcImage.Width, srcImage.Height), 0, 0, 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( 0, 0, sourceImage.Width, sourceImage.Height),
0, 0, 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),
0, 0, 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();
}
}
/// <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( 0, 0, srcImage.Width, srcImage.Height), 0, 0, 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( 0, 0, sourceImage.Width, sourceImage.Height),
0, 0, 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),
0, 0, 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;
}
}
/// <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
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類文件
希望有所幫助~