戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码)
生活随笔
收集整理的這篇文章主要介紹了
戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
關于Graphics也有了基本了解下面想說的的是學這個東東干什么呢,到底如何應用
目前常見應用
1、驗證碼(參照網上的)
2、打印排版(會提到關于條形碼大小設置)
3、自定義控件
一、驗證碼
1 class ValidateCode 2 { 3 #region 定義和初始化配置字段 4 5 //用戶存取驗證碼字符串 6 public string validationCode = String.Empty; 7 8 //生成的驗證碼字符串 9 public char[] chars = null; 10 11 /// <summary> 12 /// 獲取隨機驗證碼 13 /// </summary> 14 public String ValidationCode 15 { 16 get { return validationCode; } 17 } 18 19 /// <summary> 20 /// 驗證碼字符串的長度 21 /// </summary> 22 private Int32 validationCodeCount = 4; 23 24 /// <summary> 25 /// 獲取和設置驗證碼字符串的長度 26 /// </summary> 27 public Int32 ValidationCodeCount 28 { 29 get { return validationCodeCount; } 30 set { validationCodeCount = value; } 31 } 32 33 /// <summary> 34 /// 畫板對象 35 /// </summary> 36 Graphics dc = null; 37 38 //驗證碼的寬度,默認為130 39 private int bgWidth = 130; 40 41 /// <summary> 42 /// 驗證碼的寬度,默認為130 43 /// </summary> 44 public Int32 Width 45 { 46 get { return bgWidth; } 47 set { bgWidth = value; } 48 } 49 50 //驗證碼的寬度,默認為130 51 private int bgHeight = 40; 52 53 /// <summary> 54 /// 驗證碼的高度,默認為40 55 /// </summary> 56 public Int32 Height 57 { 58 get { return bgHeight; } 59 set { bgHeight = value; } 60 } 61 62 //字體大小 字體最小值 63 private int fontMinSize = 20; 64 65 /// <summary> 66 /// 驗證碼字體的最小值,默認為20,建議不小于15像素 67 /// </summary> 68 public Int32 FontMinSize 69 { 70 get { return fontMinSize; } 71 set { fontMinSize = value; } 72 } 73 //字體大小 字體最大值 74 private Int32 fontMaxSize = 25; 75 76 /// <summary> 77 /// 驗證碼字體的最大值,默認為25 78 /// </summary> 79 public Int32 FontMaxSize 80 { 81 get { return fontMaxSize; } 82 set { fontMaxSize = value; } 83 } 84 85 //驗證碼字體的顏色 86 private Color[] fontColor = { }; 87 88 /// <summary> 89 /// 驗證碼字體的顏色,默認為系統自動生成字體顏色 90 /// </summary> 91 public Color[] FontColor 92 { 93 get { return fontColor; } 94 set { fontColor = value; } 95 } 96 97 private Color backColor = Color.FromArgb(243, 255, 255); 98 99 /// <summary> 100 /// 驗證碼的背景色,默認為Color.FromArgb(243, 251, 254) 101 /// </summary> 102 public Color BackgroundColor 103 { 104 get { return backColor; } 105 set { backColor = value; } 106 } 107 108 //貝塞爾曲線的條數,默認為3條 109 private Int32 bezierCount = 3; 110 111 /// <summary> 112 /// 貝塞爾曲線的條數,默認為3條 113 /// </summary> 114 public Int32 BezierCount 115 { 116 get { return bezierCount; } 117 set { bezierCount = value; } 118 } 119 120 //直線條數,默認為3條 121 private Int32 lineCount = 3; 122 123 /// <summary> 124 /// 直線條數,默認為3條 125 /// </summary> 126 public Int32 LineCount 127 { 128 get { return lineCount; } 129 set { lineCount = value; } 130 } 131 132 //隨機字符串列表 133 private String charCollection = "2,3,4,5,6,7,8,9,a,s,d,f,g,h,z,c,v,b,n,m,k,q,w,e,r,t,y,u,p,A,S,D,F,G,H,Z,C,V,B,N,M,K,Q,W,E,R,T,Y,U,P"; //定義驗證碼字符及出現頻次 ,避免出現0 o j i l 1 x; 134 135 /// <summary> 136 /// 隨機字符串列表,請使用英文狀態下的逗號分隔 137 /// </summary> 138 public String CharCollection 139 { 140 get { return charCollection; } 141 set { charCollection = value; } 142 } 143 144 //驗證碼字符串個數,默認為4個字符 145 private Int32 intCount = 4; 146 147 /// <summary> 148 /// 驗證碼字符串個數,默認為4個字符 149 /// </summary> 150 public Int32 IntCount 151 { 152 get { return intCount; } 153 set { intCount = value; } 154 } 155 156 //是否添加噪點,默認添加,噪點顏色為系統隨機生成。 157 private Boolean isPixel = true; 158 /// <summary> 159 /// 是否添加噪點,默認添加,噪點顏色為系統隨機生成。 160 /// </summary> 161 public Boolean IsPixel 162 { 163 get { return isPixel; } 164 set { isPixel = value; } 165 } 166 167 //是否添加隨機噪點字符串,默認添加 168 private Boolean isRandString = true; 169 /// <summary> 170 /// 是否添加隨機噪點字符串,默認添加 171 /// </summary> 172 public Boolean IsRandString 173 { 174 get { return isRandString; } 175 set { isRandString = value; } 176 } 177 178 /// <summary> 179 /// 隨機背景字符串的個數 180 /// </summary> 181 public Int32 RandomStringCount 182 { 183 get; set; 184 } 185 186 //隨機背景字符串的大小 187 private Int32 randomStringFontSize = 9; 188 /// <summary> 189 /// 隨機背景字符串的大小 190 /// </summary> 191 public Int32 RandomStringFontSize 192 { 193 get { return randomStringFontSize; } 194 set { randomStringFontSize = value; } 195 } 196 197 /// <summary> 198 /// 是否對圖片進行扭曲 199 /// </summary> 200 public Boolean IsTwist 201 { 202 get; set; 203 } 204 205 /// <summary> 206 /// 邊框樣式 207 /// </summary> 208 public enum BorderStyle 209 { 210 /// <summary> 211 /// 無邊框 212 /// </summary> 213 None, 214 /// <summary> 215 /// 矩形邊框 216 /// </summary> 217 Rectangle, 218 /// <summary> 219 /// 圓角邊框 220 /// </summary> 221 RoundRectangle 222 } 223 224 /// <summary> 225 /// 驗證碼字符串隨機轉動的角度 默認40 226 /// </summary> 227 private Int32 rotationAngle = 40; 228 /// <summary> 229 /// 驗證碼字符串隨機轉動的角度的最大值 230 /// </summary> 231 public Int32 RotationAngle 232 { 233 get { return rotationAngle; } 234 set { rotationAngle = value; } 235 } 236 237 /// <summary> 238 /// 設置或獲取邊框樣式 239 /// </summary> 240 public BorderStyle Border 241 { 242 get; set; 243 } 244 245 /// <summary> 246 /// 對驗證碼圖片進行高斯模糊的閥值,如果設置為0 247 /// </summary> 248 private Double gaussianDeviation = 0; 249 250 /// <summary> 251 /// 對驗證碼圖片進行高斯模糊的閥值,如果設置為0,則不對圖片進行高斯模糊,該設置可能會對圖片處理的性能有較大影響 252 /// </summary> 253 public Double GaussianDeviation 254 { 255 get { return gaussianDeviation; } 256 set { gaussianDeviation = value; } 257 } 258 private Int32 brightnessValue = 0; 259 /// <summary> 260 /// 對圖片進行暗度和亮度的調整,如果該值為0,則不調整。該設置會對圖片處理性能有較大影響 261 /// </summary> 262 public Int32 BrightnessValue 263 { 264 get { return brightnessValue; } 265 set { brightnessValue = value; } 266 } 267 268 #endregion 269 270 271 private Point[] strPoint = null; 272 273 Random random = new Random(); 274 275 /// <summary> 276 /// 構造函數,用于初始化常用變量 277 /// </summary> 278 public void DrawValidationCode() 279 { 280 //隨機對象 281 //Random類所取到的系統時鐘種子接近甚至完全一樣 282 //解決方案:new Random(Guid.NewGuid().GetHashCode()); 283 random = new Random(Guid.NewGuid().GetHashCode()); 284 //坐標數組 285 strPoint = new Point[validationCodeCount + 1]; 286 if (gaussianDeviation < 0) 287 gaussianDeviation = 0; 288 } 289 290 /// <summary> 291 /// 生成驗證碼 292 /// 思路:多張圖片合成 293 /// 1.驗證碼背景圖片 294 /// 1.1.背景包含 295 /// 1.1.1.背景顏色 296 /// 1.1.2.噪點 297 /// 1.1.3.干擾文字 298 /// 1.1.4.干擾線條(直線、曲線) 299 /// 2.驗證碼字符 300 /// 3.驗證碼圖片扭曲 301 /// 4.驗證碼圖片模糊 302 /// 5.驗證碼圖片亮度 303 /// 6.驗證碼圖片保持在內存流中 304 /// </summary> 305 /// <param name="target">用于存儲圖片的一般字節序列</param> 306 public MemoryStream CreateImage(string code) 307 { 308 MemoryStream target = new MemoryStream(); 309 // 定義圖片對象大小, 310 Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1); 311 // 定義 Graphics(畫板)根據圖片對象 312 dc = Graphics.FromImage(bit); 313 /* 314 SmoothingModeAntiAlias 指定消除鋸齒的呈現。 315 SmoothingModeDefault 指定默認模式。 316 SmoothingModeHighQuality 指定高質量、低速度呈現。 317 SmoothingModeHighSpeed 指定高速度、低質量呈現。 318 SmoothingModeInvalid 指定一個無效模式。 319 SmoothingModeNone 指定不消除鋸齒。 320 */ 321 dc.SmoothingMode = SmoothingMode.HighQuality; 322 //文本的呈現模式 323 dc.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; 324 // 插補模式 325 dc.InterpolationMode = InterpolationMode.HighQualityBilinear; 326 //合成圖像的呈現質量 327 dc.CompositingQuality = CompositingQuality.HighQuality; 328 try 329 { 330 //清空畫板,指定背景色(白色) 331 dc.Clear(Color.White); 332 DrawValidationCode(); 333 //DrawImageUnscaled 在指定的位置使用圖像的原始物理大小繪制指定的圖像 334 // 驗證碼背景 335 dc.DrawImageUnscaled(DrawBackground(), 0, 0); 336 // 驗證碼字符 337 dc.DrawImageUnscaled(DrawRandomString(code), 0, 0); 338 //對圖片文字進行扭曲 339 bit = AdjustRippleEffect(bit, 5); 340 //對圖片進行高斯模糊 341 if (gaussianDeviation > 0) 342 { 343 Gaussian gau = new Gaussian(); 344 bit = gau.FilterProcessImage(gaussianDeviation, bit); 345 } 346 //進行暗度和亮度處理 347 if (brightnessValue != 0) 348 { 349 //對圖片進行調暗處理 350 bit = AdjustBrightness(bit, brightnessValue); 351 } 352 bit.Save(target, ImageFormat.Jpeg); 353 //輸出圖片流 354 return target; 355 356 } 357 finally 358 { 359 //brush.Dispose(); 360 bit.Dispose(); 361 dc.Dispose(); 362 } 363 } 364 365 #region 畫驗證碼背景,例如,增加早點,添加曲線和直線等 366 /// <summary> 367 /// 畫驗證碼背景,例如,增加早點,添加曲線和直線等 368 /// 1.1.背景包含 369 /// 1.1.1.背景顏色 370 /// 1.1.2.噪點 371 /// 1.1.3.干擾文字 372 /// 1.1.4.干擾線條(直線、曲線) 373 /// </summary> 374 /// <returns>Bitmap 對象</returns> 375 private Bitmap DrawBackground() 376 { 377 Bitmap bit = new Bitmap(bgWidth + 1, bgHeight + 1); 378 Graphics g = Graphics.FromImage(bit); 379 g.SmoothingMode = SmoothingMode.HighQuality; 380 g.Clear(Color.White); 381 Rectangle rectangle = new Rectangle(0, 0, bgWidth, bgHeight); 382 Brush brush = new SolidBrush(backColor); 383 //填充矩形 384 g.FillRectangle(brush, rectangle); 385 //畫噪點 386 if (isPixel) 387 { 388 g.DrawImageUnscaled(DrawRandomPixel(30), 0, 0); 389 } 390 // 背景干擾字符 391 g.DrawImageUnscaled(DrawRandBgString(), 0, 0); 392 //畫曲線 393 //g.DrawImageUnscaled(DrawRandomBezier(bezierCount), 0, 0); 394 //畫直線 395 //g.DrawImageUnscaled(DrawRandomLine(lineCount), 0, 0); 396 if (Border == BorderStyle.Rectangle) 397 { 398 //繪制邊框 399 g.DrawRectangle(new Pen(Color.FromArgb(90, 87, 46)), 0, 0, bgWidth, bgHeight); 400 } 401 else if (Border == BorderStyle.RoundRectangle) 402 { 403 //畫圓角 404 DrawRoundRectangle(g, rectangle, Color.FromArgb(90, 87, 46), 1, 3); 405 } 406 return bit; 407 } 408 #endregion 409 410 #region 畫隨機噪點 411 /// <summary> 412 /// 畫隨機噪點 413 /// 在指定區域中隨機設置像素點的顏色 414 /// </summary> 415 /// <param name="pixNum">噪點的百分比</param> 416 /// <returns></returns> 417 public Bitmap DrawRandomPixel(Int32 pixNum) 418 { 419 Bitmap b = new Bitmap(bgWidth, bgHeight); 420 //透明化 421 b.MakeTransparent(); 422 Graphics graph = Graphics.FromImage(b); 423 graph.SmoothingMode = SmoothingMode.HighQuality; 424 graph.InterpolationMode = InterpolationMode.HighQualityBilinear; 425 //畫噪點 426 for (int i = 0; i < (bgHeight * bgWidth) / pixNum; i++) 427 { 428 int x = random.Next(b.Width); 429 int y = random.Next(b.Height); 430 //設置隨機像素點的顏色 431 b.SetPixel(x, y, GetRandomDeepColor()); 432 //下移坐標重新畫點 433 if ((x + 1) < b.Width && (y + 1) < b.Height) 434 { 435 //畫圖片的前景噪音點 436 graph.DrawRectangle(new Pen(Color.Silver), random.Next(b.Width), random.Next(b.Height), 1, 1); 437 } 438 } 439 return b; 440 } 441 #endregion 442 443 #region 畫干擾背景文字 444 /// <summary> 445 /// 畫背景干擾文字 446 /// </summary> 447 /// <returns></returns> 448 private Bitmap DrawRandBgString() 449 { 450 Bitmap b = new Bitmap(bgWidth, bgHeight); 451 String[] randStr = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; 452 //設置透明 453 b.MakeTransparent(); 454 Graphics g = Graphics.FromImage(b); 455 g.Clear(Color.Transparent); 456 g.PixelOffsetMode = PixelOffsetMode.HighQuality; 457 g.SmoothingMode = SmoothingMode.HighQuality; 458 g.TextRenderingHint = TextRenderingHint.AntiAlias; 459 g.InterpolationMode = InterpolationMode.HighQualityBilinear; 460 //設置字體顯示格式 461 StringFormat format = new StringFormat(StringFormatFlags.NoClip); 462 format.Alignment = StringAlignment.Center; 463 format.LineAlignment = StringAlignment.Center; 464 FontFamily f = new FontFamily(GenericFontFamilies.Serif); 465 Font textFont = new Font(f, randomStringFontSize, FontStyle.Underline); 466 int randAngle = 60; //隨機轉動角度 467 for (int i = 0; i < RandomStringCount; i++) 468 { 469 Brush brush = new System.Drawing.SolidBrush(GetRandomLightColor()); 470 Point pot = new Point(random.Next(5, bgWidth - 5), random.Next(5, bgHeight - 5)); 471 //隨機轉動的度數 472 float angle = random.Next(-randAngle, randAngle); 473 //轉動畫布 474 g.RotateTransform(angle); 475 g.DrawString(randStr[random.Next(randStr.Length)], textFont, brush, pot, format); 476 //轉回去,為下一個字符做準備 477 g.RotateTransform(-angle); 478 //釋放資源 479 brush.Dispose(); 480 } 481 textFont.Dispose(); 482 format.Dispose(); 483 f.Dispose(); 484 return b; 485 } 486 #endregion 487 488 #region 隨機生成貝塞爾曲線 489 /// <summary> 490 /// 隨機生成貝塞爾曲線 491 /// </summary> 492 /// <param name="bmp">一個圖片的實例</param> 493 /// <param name="lineNum">線條數量</param> 494 /// <returns></returns> 495 public Bitmap DrawRandomBezier(Int32 lineNum) 496 { 497 Bitmap b = new Bitmap(bgWidth, bgHeight); 498 b.MakeTransparent(); 499 Graphics g = Graphics.FromImage(b); 500 g.Clear(Color.Transparent); 501 g.SmoothingMode = SmoothingMode.HighQuality; 502 g.PixelOffsetMode = PixelOffsetMode.HighQuality; 503 GraphicsPath gPath1 = new GraphicsPath(); 504 Int32 lineRandNum = random.Next(lineNum); 505 for (int i = 0; i < (lineNum - lineRandNum); i++) 506 { 507 Pen p = new Pen(GetRandomDeepColor()); 508 Point[] point = { 509 new Point(random.Next(1, (b.Width / 10)), random.Next(1, (b.Height))), 510 new Point(random.Next((b.Width / 10) * 2, (b.Width / 10) * 4), random.Next(1, (b.Height))), 511 new Point(random.Next((b.Width / 10) * 4, (b.Width / 10) * 6), random.Next(1, (b.Height))), 512 new Point(random.Next((b.Width / 10) * 8, b.Width), random.Next(1, (b.Height))) 513 }; 514 gPath1.AddBeziers(point); 515 g.DrawPath(p, gPath1); 516 p.Dispose(); 517 } 518 for (int i = 0; i < lineRandNum; i++) 519 { 520 Pen p = new Pen(GetRandomDeepColor()); 521 Point[] point = { 522 new Point(random.Next(1, b.Width), random.Next(1, b.Height)), 523 new Point(random.Next((b.Width / 10) * 2, b.Width), random.Next(1, b.Height)), 524 new Point(random.Next((b.Width / 10) * 4, b.Width), random.Next(1, b.Height)), 525 new Point(random.Next(1, b.Width), random.Next(1, b.Height)) 526 }; 527 gPath1.AddBeziers(point); 528 g.DrawPath(p, gPath1); 529 p.Dispose(); 530 } 531 return b; 532 } 533 #endregion 534 535 #region 畫直線 536 /// <summary> 537 /// 畫直線 538 /// </summary> 539 /// <param name="bmp">一個bmp實例</param> 540 /// <param name="lineNum">線條個數</param> 541 /// <returns></returns> 542 public Bitmap DrawRandomLine(Int32 lineNum) 543 { 544 if (lineNum < 0) throw new ArgumentNullException("參數bmp為空!"); 545 Bitmap b = new Bitmap(bgWidth, bgHeight); 546 b.MakeTransparent(); 547 Graphics g = Graphics.FromImage(b); 548 g.Clear(Color.Transparent); 549 g.PixelOffsetMode = PixelOffsetMode.HighQuality; 550 g.SmoothingMode = SmoothingMode.HighQuality; 551 for (int i = 0; i < lineNum; i++) 552 { 553 Pen p = new Pen(GetRandomDeepColor()); 554 Point pt1 = new Point(random.Next(1, (b.Width / 5) * 2), random.Next(b.Height)); 555 Point pt2 = new Point(random.Next((b.Width / 5) * 3, b.Width), random.Next(b.Height)); 556 g.DrawLine(p, pt1, pt2); 557 p.Dispose(); 558 } 559 return b; 560 } 561 #endregion 562 563 #region 寫入驗證碼的字符串 564 /// <summary> 565 /// 寫入驗證碼的字符串 566 /// </summary> 567 private Bitmap DrawRandomString(string Code) 568 { 569 if (fontMaxSize >= (bgHeight / 5) * 4) 570 throw new ArgumentException("字體最大值參數FontMaxSize與驗證碼高度相近,這會導致描繪驗證碼字符串時出錯,請重新設置參數!"); 571 Bitmap b = new Bitmap(bgWidth, bgHeight); 572 b.MakeTransparent(); 573 Graphics g = Graphics.FromImage(b); 574 g.Clear(Color.Transparent); 575 g.PixelOffsetMode = PixelOffsetMode.Half; 576 g.SmoothingMode = SmoothingMode.HighQuality; 577 g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; 578 g.InterpolationMode = InterpolationMode.HighQualityBilinear; 579 chars = Code.ToCharArray(); //拆散字符串成單字符數組 580 validationCode = chars.ToString(); 581 //設置字體顯示格式 582 StringFormat format = new StringFormat(StringFormatFlags.NoClip); 583 format.Alignment = StringAlignment.Center; 584 format.LineAlignment = StringAlignment.Center; 585 FontFamily f = new FontFamily(GenericFontFamilies.Monospace); 586 Int32 charNum = chars.Length; 587 Point sPoint = new Point(); 588 Int32 fontSize = 12; 589 validationCodeCount = charNum; 590 for (int i = 0; i < validationCodeCount; i++) 591 { 592 //定義字體 593 Font textFont = new Font(f, random.Next(fontMinSize, fontMaxSize), FontStyle.Bold); 594 //定義畫刷,用于寫字符串 595 //Brush brush = new SolidBrush(GetRandomDeepColor()); 596 Int32 textFontSize = Convert.ToInt32(textFont.Size); 597 fontSize = textFontSize; 598 //Point point = new Point(random.Next((bgWidth / charNum) * i + 5, (bgWidth / charNum) * (i + 1)), random.Next(bgHeight / 5 + textFontSize / 2, bgHeight - textFontSize / 2)); 599 // 字符位置坐標 600 Point point = new Point(random.Next((bgWidth / charNum) * i + 2, (bgWidth / charNum) * (i + 1) - (textFontSize / 2)), random.Next(bgHeight / 5 + textFontSize / 2, bgHeight - textFontSize / 2)); 601 //如果當前字符X坐標小于字體的二分之一大小 602 if (point.X < textFontSize / 2) 603 { 604 point.X = point.X + textFontSize / 2; 605 } 606 //防止文字疊加 607 if (i > 0 && (point.X - sPoint.X < (textFontSize / 2 + textFontSize / 2))) 608 { 609 point.X = point.X + textFontSize; 610 } 611 //如果當前字符X坐標大于圖片寬度,就減去字體的寬度 612 if (point.X > (bgWidth - textFontSize / 2)) 613 { 614 point.X = bgWidth - textFontSize / 2; 615 } 616 sPoint = point; 617 float angle = random.Next(-rotationAngle, rotationAngle);//轉動的度數 618 g.TranslateTransform(point.X, point.Y); 619 g.RotateTransform(angle); 620 621 Rectangle myretang = new Rectangle(0, 1, Convert.ToInt32(textFont.Size), Convert.ToInt32(textFont.Size)); 622 Color c = GetRandomDeepColor(); 623 //設置漸變畫刷 624 LinearGradientBrush mybrush2 = new LinearGradientBrush(myretang, c, GetLightColor(c, 120), random.Next(180)); 625 g.DrawString(chars[i].ToString(), textFont, mybrush2, 1, 1, format); 626 627 g.RotateTransform(-angle);//轉回去 628 g.TranslateTransform(-point.X, -point.Y);//移動光標到指定位置,每個字符緊湊顯示,避免被軟件識別 629 strPoint[i] = point; 630 textFont.Dispose(); 631 mybrush2.Dispose(); 632 } 633 return b; 634 } 635 #endregion 636 637 #region 增加或減少亮度 638 /// <summary> 639 /// 增加或減少亮度 640 /// </summary> 641 /// <param name="img">System.Drawing.Image Source </param> 642 /// <param name="valBrightness">0~255</param> 643 /// <returns></returns> 644 public System.Drawing.Bitmap AdjustBrightness(System.Drawing.Image img, int valBrightness) 645 { 646 // 讀入欲轉換的圖片並轉成為 Bitmap 647 System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img); 648 for (int y = 0; y < bitmap.Height; y++) 649 { 650 for (int x = 0; x < bitmap.Width; x++) 651 { 652 // 取得每一個 pixel 653 var pixel = bitmap.GetPixel(x, y); 654 // 判斷 如果處理過後 255 就設定為 255 如果小於則設定為 0 655 var pR = ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness) < 0 ? 0 : ((pixel.R + valBrightness > 255) ? 255 : pixel.R + valBrightness); 656 var pG = ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness) < 0 ? 0 : ((pixel.G + valBrightness > 255) ? 255 : pixel.G + valBrightness); 657 var pB = ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness) < 0 ? 0 : ((pixel.B + valBrightness > 255) ? 255 : pixel.B + valBrightness); 658 // 將改過的 RGB 寫回 659 System.Drawing.Color newColor = System.Drawing.Color.FromArgb(pixel.A, pR, pG, pB); 660 bitmap.SetPixel(x, y, newColor); 661 } 662 } 663 // 回傳結果 664 return bitmap; 665 } 666 #endregion 667 668 #region 水波紋效果 669 /// <summary> 670 /// 水波紋效果 671 /// </summary> 672 /// <param name="src"></param> 673 /// <param name="nWave">坡度</param> 674 /// www.it165.net 675 /// <returns></returns> 676 public Bitmap AdjustRippleEffect(Bitmap src, short nWave) 677 { 678 int nWidth = src.Width; 679 int nHeight = src.Height; 680 // 透過公式進行水波紋的採樣 681 PointF[,] fp = new PointF[nWidth, nHeight]; 682 Point[,] pt = new Point[nWidth, nHeight]; 683 Point mid = new Point(); 684 mid.X = nWidth / 2; 685 mid.Y = nHeight / 2; 686 double newX, newY; 687 double xo, yo; 688 //先取樣將水波紋座標跟RGB取出 689 for (int x = 0; x < nWidth; ++x) 690 for (int y = 0; y < nHeight; ++y) 691 { 692 xo = ((double)nWave * Math.Sin(2.0 * 3.1415 * (float)y / 128.0)); 693 yo = ((double)nWave * Math.Cos(2.0 * 3.1415 * (float)x / 128.0)); 694 newX = (x + xo); 695 newY = (y + yo); 696 if (newX > 0 && newX < nWidth) 697 { 698 fp[x, y].X = (float)newX; 699 pt[x, y].X = (int)newX; 700 } 701 else 702 { 703 fp[x, y].X = (float)0.0; 704 pt[x, y].X = 0; 705 } 706 if (newY > 0 && newY < nHeight) 707 { 708 fp[x, y].Y = (float)newY; 709 pt[x, y].Y = (int)newY; 710 } 711 else 712 { 713 fp[x, y].Y = (float)0.0; 714 pt[x, y].Y = 0; 715 } 716 } 717 //進行合成 718 Bitmap bSrc = (Bitmap)src.Clone(); 719 // 依照 Format24bppRgb 每三個表示一 Pixel 0: 藍 1: 綠 2: 紅 720 BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 721 BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 722 int scanline = bitmapData.Stride; 723 IntPtr Scan0 = bitmapData.Scan0; 724 IntPtr SrcScan0 = bmSrc.Scan0; 725 //指針在c#中是不提倡使用的,有關指針的操作被認為是不安全的(unsafe)。因此運行這段代碼之前,先要改一個地方,否則編譯不過無法運行。 726 //修改方法:找到你的項目,在項目圖標上點右鍵,選項目屬性(Properties),Build標簽頁里把Allow unsafe code勾選上 727 unsafe 728 { 729 //指針 730 byte* p = (byte*)(void*)Scan0; 731 byte* pSrc = (byte*)(void*)SrcScan0; 732 int nOffset = bitmapData.Stride - src.Width * 3; 733 int xOffset, yOffset; 734 for (int y = 0; y < nHeight; ++y) 735 { 736 for (int x = 0; x < nWidth; ++x) 737 { 738 xOffset = pt[x, y].X; 739 yOffset = pt[x, y].Y; 740 if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth) 741 { 742 p[0] = pSrc[(yOffset * scanline) + (xOffset * 3)]; 743 p[1] = pSrc[(yOffset * scanline) + (xOffset * 3) + 1]; 744 p[2] = pSrc[(yOffset * scanline) + (xOffset * 3) + 2]; 745 } 746 p += 3; 747 } 748 p += nOffset; 749 } 750 } 751 src.UnlockBits(bitmapData); 752 bSrc.UnlockBits(bmSrc); 753 return src; 754 } 755 #endregion 756 757 #region 生成隨機字符串 758 /// <summary> 759 /// 生成隨機字符串 760 /// </summary> 761 /// <returns></returns> 762 public string GetRandomString(Int32 textLength) 763 { 764 string[] randomArray = charCollection.Split(','); //將字符串生成數組 765 int arrayLength = randomArray.Length; 766 string randomString = ""; 767 for (int i = 0; i < textLength; i++) 768 { 769 randomString += randomArray[random.Next(0, arrayLength)]; 770 } 771 return randomString; //長度是textLength +1 772 } 773 #endregion 774 775 #region 隨機生成顏色值 776 /// <summary> 777 /// 生成隨機深顏色 778 /// </summary> 779 /// <returns></returns> 780 public Color GetRandomDeepColor() 781 { 782 int nRed, nGreen, nBlue; 783 // nBlue,nRed nGreen 相差大一點 nGreen 小一些 784 //int high = 255; 785 int redLow = 160; 786 int greenLow = 100; 787 int blueLow = 160; 788 nRed = random.Next(redLow); 789 nGreen = random.Next(greenLow); 790 nBlue = random.Next(blueLow); 791 Color color = Color.FromArgb(nRed, nGreen, nBlue); 792 return color; 793 } 794 /// <summary> 795 /// 生成隨機淺顏色 796 /// </summary> 797 /// <returns>randomColor</returns> 798 public Color GetRandomLightColor() 799 { 800 int nRed, nGreen, nBlue; 801 //越大顏色越淺 802 int low = 180; //色彩的下限 803 int high = 255; //色彩的上限 804 nRed = random.Next(high) % (high - low) + low; 805 nGreen = random.Next(high) % (high - low) + low; 806 nBlue = random.Next(high) % (high - low) + low; 807 Color color = Color.FromArgb(nRed, nGreen, nBlue); 808 return color; 809 } 810 /// <summary> 811 /// 獲取與當前顏色值相加后的顏色 812 /// </summary> 813 /// <param name="c"></param> 814 /// <returns></returns> 815 public Color GetLightColor(Color c, Int32 value) 816 { 817 int nRed = c.R, nGreen = c.G, nBlue = c.B; 818 //越大顏色越淺 819 if (nRed + value < 255 && nRed + value > 0) 820 { 821 nRed = c.R + 40; 822 } 823 if (nGreen + value < 255 && nGreen + value > 0) 824 { 825 nGreen = c.G + 40; 826 } 827 if (nBlue + value < 255 && nBlue + value > 0) 828 { 829 nBlue = c.B + 40; 830 } 831 Color color = Color.FromArgb(nRed, nGreen, nBlue); 832 return color; 833 } 834 #endregion 835 836 #region 繪制圓角矩形 837 /// <summary> 838 /// C# GDI+ 繪制圓角矩形 839 /// </summary> 840 /// <param name="g">Graphics 對象</param> 841 /// <param name="rectangle">Rectangle 對象,圓角矩形區域</param> 842 /// <param name="borderColor">邊框顏色</param> 843 /// <param name="borderWidth">邊框寬度</param> 844 /// <param name="r">圓角半徑</param> 845 private static void DrawRoundRectangle(Graphics g, Rectangle rectangle, Color borderColor, float borderWidth, int r) 846 { 847 // 如要使邊緣平滑,請取消下行的注釋 848 g.SmoothingMode = SmoothingMode.HighQuality; 849 Pen p = new Pen(borderColor, borderWidth); 850 // 調用 getRoundRectangle 得到圓角矩形的路徑,然后再進行繪制 851 g.DrawPath(p, getRoundRectangle(rectangle, r)); 852 } 853 #endregion 854 855 #region 根據普通矩形得到圓角矩形的路徑 856 /// <summary> 857 /// 根據普通矩形得到圓角矩形的路徑 858 /// </summary> 859 /// <param name="rectangle">原始矩形</param> 860 /// <param name="r">半徑</param> 861 /// <returns>圖形路徑</returns> 862 private static GraphicsPath getRoundRectangle(Rectangle rectangle, int r) 863 { 864 int l = 2 * r; 865 // 把圓角矩形分成八段直線、弧的組合,依次加到路徑中 866 GraphicsPath gp = new GraphicsPath(); 867 gp.AddLine(new Point(rectangle.X + r, rectangle.Y), new Point(rectangle.Right - r, rectangle.Y)); 868 gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Y, l, l), 270F, 90F); 869 gp.AddLine(new Point(rectangle.Right, rectangle.Y + r), new Point(rectangle.Right, rectangle.Bottom - r)); 870 gp.AddArc(new Rectangle(rectangle.Right - l, rectangle.Bottom - l, l, l), 0F, 90F); 871 gp.AddLine(new Point(rectangle.Right - r, rectangle.Bottom), new Point(rectangle.X + r, rectangle.Bottom)); 872 gp.AddArc(new Rectangle(rectangle.X, rectangle.Bottom - l, l, l), 90F, 90F); 873 gp.AddLine(new Point(rectangle.X, rectangle.Bottom - r), new Point(rectangle.X, rectangle.Y + r)); 874 gp.AddArc(new Rectangle(rectangle.X, rectangle.Y, l, l), 180F, 90F); 875 return gp; 876 } 877 #endregion 878 }View Code
調用
1 private void frmValidateCode_Load(object sender, EventArgs e) 2 { 3 ValidateCode vCode = new ValidateCode(); 4 string code = vCode.GetRandomString(5); 5 MemoryStream stream = vCode.CreateImage(code); 6 pictureBox1.Image = new Bitmap(stream); 7 }
效果
?
轉載于:https://www.cnblogs.com/WarBlog/p/11189717.html
總結
以上是生活随笔為你收集整理的戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 导致男性不育的因素
- 下一篇: python练习:猜价钱小游戏