【转】C#使用ESC指令控制POS打印机打印小票

   1 1.前言
   2  
   3 
   4 C#打印小票可以与普通打印机一样,调用PrintDocument实现。也可以发送标注你的ESC指令实现。由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的pos打印机,并且无法发送控制指令实现pos打印机的切纸、走纸等动作。因此个人建议使用ESC指令进行打印会更通用。
   5 
   6 本类需要调用 ImageProcessor.cs
   7 
   8  
   9 
  10 2.POS机打印小票ReceiptHelper
  11 using System;
  12 
  13 using System.Collections.Generic;
  14 
  15 using System.Text;
  16 
  17 using System.Runtime.InteropServices;
  18 
  19 using System.Threading;
  20 
  21 using System.Drawing;
  22 
  23 using System.Management;
  24 
  25 using System.IO;
  26 
  27 using LaisonTech.MediaLib;
  28 
  29 using LaisonTech.CommonBLL;
  30 
  31 using Microsoft.Win32.SafeHandles;
  32 
  33  
  34 
  35 namespace LaisonTech.MediaLib
  36 
  37 {
  38 
  39  
  40 
  41 #region 结构体定义
  42 
  43  
  44 
  45     [StructLayout(LayoutKind.Sequential)]
  46 
  47     public struct OVERLAPPED
  48 
  49     {
  50 
  51         int Internal;
  52 
  53         int InternalHigh;
  54 
  55         int Offset;
  56 
  57         int OffSetHigh;
  58 
  59         int hEvent;
  60 
  61     };
  62 
  63  
  64 
  65     [StructLayout(LayoutKind.Sequential)]
  66 
  67     public struct PRINTER_DEFAULTS
  68 
  69     {
  70 
  71  
  72 
  73         public int pDatatype;
  74 
  75  
  76 
  77         public int pDevMode;
  78 
  79  
  80 
  81         public int DesiredAccess;
  82 
  83  
  84 
  85     }
  86 
  87  
  88 
  89     /// <summary>
  90 
  91     /// 对齐方式
  92 
  93     /// </summary>
  94 
  95     public enum eTextAlignMode
  96 
  97     {
  98 
  99         Left = 0,
 100 
 101         Middle = 1,
 102 
 103         Right = 2
 104 
 105     }
 106 
 107  
 108 
 109 #endregion
 110 
 111  
 112 
 113     /// <summary>
 114 
 115     /// 小票打印类
 116 
 117 /// 使用方法:
 118 
 119 /// 1 GetPrinterList获取已经安装的所有打印机列表.
 120 
 121 ///  Open 打开指定打印机
 122 
 123 /// 2 控制打印机动作、执行打印内容之前,必须先调用StartPrint,准备向打印机发送控制指令
 124 
 125 /// 3 调用SetLeft, SetBold, SetAlignMode, SetFontSize ... ...设置打印参数
 126 
 127 /// 4  PrintText 打印内容.注意:打印该行内容后会自动换行(本类会在该行内容末尾添加一个换行符)
 128 
 129 ///   PrintImageFile 或 PrintBitMap打印图片
 130 
 131 /// 5 控制指令和打印内容都发送完毕后,调用 EndPrint执行真正打印动作
 132 
 133     /// 6 退出程序前调用Close
 134 
 135     /// </summary>
 136 
 137     public class ReceiptHelper
 138 
 139     {
 140 
 141         #region 指令定义
 142 
 143        
 144 
 145         private static Byte[] Const_Init = new byte[] { 0x1B, 0x40,
 146 
 147             0x20, 0x20, 0x20, 0x0A,
 148 
 149             0x1B, 0x64,0x10};
 150 
 151  
 152 
 153         //设置左边距
 154 
 155         private const string Const_SetLeft = "1D 4C ";
 156 
 157  
 158 
 159  
 160 
 161         //设置粗体
 162 
 163         private const string Const_SetBold = "1B 45 ";
 164 
 165         private const String Const_Bold_YES = "01";
 166 
 167         private const String Const_Bold_NO = "00";
 168 
 169        
 170 
 171        
 172 
 173         //设置对齐方式
 174 
 175         private const string Const_SetAlign = "1B 61 ";
 176 
 177         private const String Const_Align_Left = "30";
 178 
 179         private const String Const_Align_Middle = "31";
 180 
 181         private const String Const_Align_Right = "32";
 182 
 183  
 184 
 185         //设置字体大小,与 SetBigFont 不能同时使用
 186 
 187         private const string Const_SetFontSize = "1D 21 ";
 188 
 189  
 190 
 191         //设置是否大字体,等同于 SetFontSize = 2
 192 
 193         //private const String Const_SetBigFontBold = "1B 21 38";
 194 
 195         //private const String Const_SetBigFontNotBold = "1B 21 30";
 196 
 197         //private const String Const_SetCancelBigFont = "1B 21 00";
 198 
 199  
 200 
 201         /// <summary>
 202 
 203         /// 打印并走纸
 204 
 205         /// </summary>
 206 
 207         private static Byte[] Const_Cmd_Print = new byte[] { 0x1B, 0x4A, 0x00 };
 208 
 209         //走纸
 210 
 211         private const string Const_FeedForward = "1B 4A ";
 212 
 213         private const string Const_FeedBack = "1B 6A ";
 214 
 215  
 216 
 217         //切纸
 218 
 219         private static Byte[]  Const_SetCut = new byte[] { 0x1D, 0x56, 0x30};
 220 
 221  
 222 
 223         //查询打印机状态
 224 
 225         private static Byte[] Const_QueryID = new byte[] { 0x1D, 0x67, 0x61};
 226 
 227  
 228 
 229         //回复帧以 ID 开头
 230 
 231         private static String Const_ResponseQueryID = "ID";
 232 
 233  
 234 
 235         /// <summary>
 236 
 237         /// 设置图标的指令
 238 
 239         /// </summary>
 240 
 241         private static Byte[] Const_SetImageCommand = new Byte[] { 0x1B, 0x2A, 0x21 };
 242 
 243  
 244 
 245 #endregion
 246 
 247        
 248 
 249         #region 常量定义
 250 
 251  
 252 
 253         /// <summary>
 254 
 255         /// 最大字体大小
 256 
 257         /// </summary>
 258 
 259         public const Int32 Const_MaxFontSize = 8;
 260 
 261         /// <summary>
 262 
 263         /// 最大走纸距离
 264 
 265         /// </summary>
 266 
 267         public const Int32 Const_MaxFeedLength = 5000;
 268 
 269  
 270 
 271         /// <summary>
 272 
 273         /// 最大高宽
 274 
 275         /// </summary>
 276 
 277         public const Int32 Const_MaxImageLength = 480;
 278 
 279        
 280 
 281         /// <summary>
 282 
 283         /// 每次通信最多打印的行数
 284 
 285         /// </summary>
 286 
 287         public const Int32 Const_OncePrintRowCount = 24;
 288 
 289  
 290 
 291         public const Int32 Const_BrightnessGate = 100;
 292 
 293  
 294 
 295         /// <summary>
 296 
 297         /// 无效句柄
 298 
 299         /// </summary>
 300 
 301         public const Int32 Const_InvalidHandle = -1;
 302 
 303         #endregion
 304 
 305  
 306 
 307         #region 私有成员
 308 
 309  
 310 
 311         /// <summary>
 312 
 313         /// 打印机句柄
 314 
 315         /// </summary>
 316 
 317         private int m_Handle = -1;
 318 
 319  
 320 
 321         /// <summary>
 322 
 323         /// 是否已经初始化
 324 
 325         /// </summary>
 326 
 327         private Boolean m_Inited = false;
 328 
 329  
 330 
 331  
 332 
 333         #endregion
 334 
 335        
 336 
 337         #region 私有函数
 338 
 339                
 340 
 341         [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 342 
 343         public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
 344 
 345             out Int32 hPrinter, IntPtr pd);
 346 
 347  
 348 
 349         [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 350 
 351         public static extern bool StartDocPrinter(Int32 hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
 352 
 353  
 354 
 355         [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 356 
 357         public static extern bool EndDocPrinter(Int32 hPrinter);
 358 
 359  
 360 
 361         [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 362 
 363         public static extern bool StartPagePrinter(Int32 hPrinter);
 364 
 365  
 366 
 367         [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 368 
 369         public static extern bool EndPagePrinter(Int32 hPrinter);
 370 
 371  
 372 
 373         [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 374 
 375         public static extern bool WritePrinter(Int32 hPrinter, Byte[] pBytes, Int32 dwCount, out Int32 dwWritten);
 376 
 377       
 378 
 379         [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
 380 
 381         public static extern bool ClosePrinter(Int32 hPrinter);
 382 
 383        
 384 
 385  
 386 
 387         /// <summary>
 388 
 389         /// 发送指令
 390 
 391         /// </summary>
 392 
 393         /// <param name="cmd"></param>
 394 
 395         /// <returns></returns>
 396 
 397         private Boolean SendCommand(Byte[] cmd)
 398 
 399         {
 400 
 401             if (m_Handle == Const_InvalidHandle || cmd == null || cmd.Length < 2)
 402 
 403             {
 404 
 405                 return false;
 406 
 407             }
 408 
 409  
 410 
 411             int writelen = 0;
 412 
 413             Boolean bl = WritePrinter(m_Handle, cmd, cmd.Length, out writelen);
 414 
 415  
 416 
 417             if (!bl) return false;
 418 
 419             return (writelen >= cmd.Length);
 420 
 421         }
 422 
 423        
 424 
 425         /// <summary>
 426 
 427         /// 发送文本格式的指令
 428 
 429         /// </summary>
 430 
 431         /// <param name="cmd"></param>
 432 
 433         /// <returns></returns>
 434 
 435         private Boolean SendCommand(String hexstrcmd)
 436 
 437         {
 438 
 439             if (m_Handle == Const_InvalidHandle || hexstrcmd == null || hexstrcmd.Length < 4)
 440 
 441             {
 442 
 443                 return false;
 444 
 445             }
 446 
 447            
 448 
 449             byte[] mybyte = null;
 450 
 451             Boolean bl = DataFormatProcessor.HexStringToBytes(hexstrcmd, out mybyte);
 452 
 453             bl = SendCommand(mybyte);
 454 
 455             return bl;
 456 
 457         }
 458 
 459  
 460 
 461    
 462 
 463         #endregion
 464 
 465  
 466 
 467         #region 内部处理 - 打印图片
 468 
 469  
 470 
 471         /// <summary>
 472 
 473         /// 把图片转换为指令字节,图片最大高宽不能超过480
 474 
 475         /// </summary>
 476 
 477         /// <param name="image"></param>
 478 
 479         /// <param name="bmpbytes"></param>
 480 
 481         /// <returns></returns>
 482 
 483         public static Boolean LoadImage(Bitmap image,
 484 
 485             ref Byte[] bitarray,ref Int32 datawidth,ref Int32 dataheight)
 486 
 487         {
 488 
 489             Int32 newwidth = 0;
 490 
 491             Int32 newheight = 0;
 492 
 493             Bitmap destimage = image;
 494 
 495             Boolean bl = false;
 496 
 497  
 498 
 499             //如果高度超过范围,或宽度超过范围,需要进行缩小
 500 
 501             if (image.Width > Const_MaxImageLength || image.Height > Const_MaxImageLength)
 502 
 503             {
 504 
 505                 //按照高度和宽度,较大的那一边,进行缩放
 506 
 507                 if (image.Width > image.Height)
 508 
 509                 {
 510 
 511                     newwidth = Const_MaxImageLength;
 512 
 513                     newheight = (Int32)(image.Height * newwidth / (float)image.Width);
 514 
 515                 }
 516 
 517                 else
 518 
 519                 {
 520 
 521                     newheight = Const_MaxImageLength;
 522 
 523                     newwidth = (Int32)(newheight * image.Width / (float)image.Height);
 524 
 525                 }
 526 
 527  
 528 
 529                 bl = ImageProcessor.ResizeImage(image, newwidth, newheight, ref destimage);
 530 
 531             }
 532 
 533  
 534 
 535             //把数据转换为字节数组
 536 
 537             bl = GetBitArray(image, ref bitarray, ref datawidth, ref dataheight);
 538 
 539             return bl;
 540 
 541         }
 542 
 543  
 544 
 545         /// <summary>
 546 
 547         /// 把图片转换为指令字节,图片最大高宽不能超过480
 548 
 549         /// 如果图片的高度不是24的整数倍,则修改为24的整数倍
 550 
 551         /// </summary>
 552 
 553         /// <param name="image"></param>
 554 
 555         /// <param name="bmpbytes"></param>
 556 
 557         /// <returns></returns>
 558 
 559         public static Boolean LoadImageFromFile(String imagefilename, ref Byte[] bmpbytes,
 560 
 561             ref Int32 width, ref Int32 height)
 562 
 563         {
 564 
 565             Bitmap img = ImageProcessor.LoadBitImage(imagefilename);
 566 
 567             if (img == null)
 568 
 569             {
 570 
 571                 return false;
 572 
 573             }
 574 
 575  
 576 
 577             Boolean bl = LoadImage(img, ref bmpbytes, ref width, ref height);
 578 
 579             return bl;
 580 
 581         }
 582 
 583        
 584 
 585         /// <summary>
 586 
 587         /// 把图片转换为位图数组,每个字节的每个比特位,对应当前像素 是否需要打印
 588 
 589         /// </summary>
 590 
 591         /// <param name="img"></param>
 592 
 593         /// <param name="allbitary"></param>
 594 
 595         /// <returns></returns>
 596 
 597         public static Boolean GetBitArray(Bitmap img,
 598 
 599             ref Byte[] allbitary, ref Int32 width, ref Int32 height)
 600 
 601         {
 602 
 603             if (img == null)
 604 
 605             {
 606 
 607                 return false;
 608 
 609             }
 610 
 611  
 612 
 613             //ESC指令格式规定:
 614 
 615             //1 打印图片时,每条指令最多只打印24行;不足24行的,也要用全0填充满数据字节
 616 
 617             //2 打印24行数据时,按照光栅模式纵向获取数据
 618 
 619             //  即先获取所有x=0的点(第0列)转换为3个字节;
 620 
 621             //  再获取所有x=1的点转换为3个字节;...直到获取到最右侧一列的点
 622 
 623             //3 打印完当前24行数据后,再获取后续24行的数据内容,直到所有的数据获取完毕
 624 
 625  
 626 
 627             //获取亮度数组
 628 
 629             Boolean[] briary = null;
 630 
 631             Boolean bl = ImageProcessor.ToBooleanArray(img, Const_BrightnessGate, ref briary);
 632 
 633             if (!bl)
 634 
 635             {
 636 
 637                 return false;
 638 
 639             }
 640 
 641  
 642 
 643             height = img.Height;//如果图像高度不是24整数倍,设置为24的整数倍       
 644 
 645             if (height % Const_OncePrintRowCount != 0)
 646 
 647             {
 648 
 649                 height = height + Const_OncePrintRowCount - height % Const_OncePrintRowCount;
 650 
 651             }
 652 
 653  
 654 
 655             width = img.Width;//如果图像宽度不是8的整数倍,设置为8的整数倍
 656 
 657             if (width % 8 != 0)
 658 
 659             {
 660 
 661                 width = width + 8 - width % 8;
 662 
 663             }
 664 
 665  
 666 
 667             Int32 bytelen = height * width / 8;//每个像素对应1个比特位,因此总字节数=像素位数/8
 668 
 669  
 670 
 671             allbitary = new Byte[bytelen];
 672 
 673  
 674 
 675             Int32 byteidxInCol = 0;//当前列里首个像素,在目标字节数组里的下标
 676 
 677             Int32 byteidx = 0;//当前像素在目标数组里的字节下标
 678 
 679             Int32 bitidx = 0;//当前像素在目标数组里当前字节里的比特位下标
 680 
 681             Int32 pixidxInCol = 0;//当前像素在当前列里的第几个位置
 682 
 683  
 684 
 685             Int32 pixidx = 0;//当前像素在原始图片里的下标
 686 
 687            
 688 
 689             Int32 rowidx = 0; //当前 处理的像素点所在行,不能超过 图像高度
 690 
 691             Int32 curprocrows = 0;//当前需要处理的行数量
 692 
 693             while (rowidx < height)
 694 
 695             {
 696 
 697                 //按照纵向次序,把当前列的24个数据,转换为3个字节
 698 
 699                 for (Int32 colidx = 0; colidx < img.Width; ++colidx)
 700 
 701                 {
 702 
 703                     //如果当前还剩余超过24行没处理,处理24行
 704 
 705                     if (rowidx + Const_OncePrintRowCount <= img.Height)
 706 
 707                     {
 708 
 709                         curprocrows = Const_OncePrintRowCount;
 710 
 711                     }
 712 
 713                     else
 714 
 715                     {
 716 
 717                         //已经不足24行,只处理剩余行数
 718 
 719                         curprocrows = img.Height - rowidx;
 720 
 721                     }
 722 
 723  
 724 
 725                     pixidxInCol = 0; //本列里从像素0开始处理
 726 
 727                     for (Int32 y = rowidx; y < rowidx + curprocrows; ++y)
 728 
 729                     {
 730 
 731                         //原始图片里像素位置
 732 
 733                         pixidx = y * img.Width + colidx;
 734 
 735  
 736 
 737                         //获取当前像素的亮度值.如果当前像素是黑点,需要把数组里的对应比特位设置为1
 738 
 739                         if (briary[pixidx])
 740 
 741                         {
 742 
 743                             bitidx = 7 - pixidxInCol % 8;//最高比特位对应首个像素.最低比特位对应末个像素
 744 
 745                             byteidx = byteidxInCol + pixidxInCol / 8; //由于最后一段可能不足24行,因此不能使用byteidx++
 746 
 747                            
 748 
 749                             DataFormatProcessor.SetBitValue(bitidx, true, ref allbitary[byteidx]);
 750 
 751                         }
 752 
 753                         pixidxInCol++;
 754 
 755                     }
 756 
 757                     byteidxInCol += 3;//每列固定24个像素,3个字节
 758 
 759                 }
 760 
 761  
 762 
 763                 rowidx += Const_OncePrintRowCount;
 764 
 765             }
 766 
 767            
 768 
 769             return true;
 770 
 771         }
 772 
 773  
 774 
 775         #endregion
 776 
 777  
 778 
 779         #region 公开函数
 780 
 781  
 782 
 783         private static ReceiptHelper m_instance = new ReceiptHelper();
 784 
 785  
 786 
 787         /// <summary>
 788 
 789         /// 当前使用的打印机名称
 790 
 791         /// </summary>
 792 
 793         public String PrinterName
 794 
 795         {
 796 
 797             get;private set;
 798 
 799         }
 800 
 801  
 802 
 803         /// <summary>
 804 
 805         /// 单件模式
 806 
 807         /// </summary>
 808 
 809         /// <returns></returns>
 810 
 811         public static ReceiptHelper GetInstance()
 812 
 813         {
 814 
 815             return m_instance;
 816 
 817         }
 818 
 819  
 820 
 821         /// <summary>
 822 
 823         /// 获取本机安装的所有打印机
 824 
 825         /// </summary>
 826 
 827         /// <returns></returns>
 828 
 829         public static List<String> GetPrinterList()
 830 
 831         {
 832 
 833             List<String> ret = new List<String>();
 834 
 835             if (PrinterSettings.InstalledPrinters.Count < 1)
 836 
 837             {
 838 
 839                 return ret;
 840 
 841             }
 842 
 843  
 844 
 845             foreach (String printername in PrinterSettings.InstalledPrinters)
 846 
 847             {
 848 
 849                 ret.Add(printername);
 850 
 851             }
 852 
 853             return ret;
 854 
 855         }
 856 
 857  
 858 
 859         /// <summary>
 860 
 861         /// 打开打印机
 862 
 863         /// </summary>
 864 
 865         /// <param name="printername"></param>
 866 
 867         /// <returns></returns>
 868 
 869         public Boolean Open(String printername)
 870 
 871         {
 872 
 873             if (m_Inited)
 874 
 875             {
 876 
 877                 return true;
 878 
 879             }
 880 
 881             Boolean bl = OpenPrinter(printername.Normalize(), out m_Handle, IntPtr.Zero); 
 882 
 883             
 884 
 885             m_Inited = (bl && m_Handle != 0); 
 886 
 887             return true;
 888 
 889         }
 890 
 891  
 892 
 893         /// <summary>
 894 
 895         /// 开始打印,在打印之前必须调用此函数
 896 
 897         /// </summary>
 898 
 899         /// <returns></returns>
 900 
 901         public Boolean StartPrint()
 902 
 903         {
 904 
 905             if (!m_Inited)
 906 
 907             {
 908 
 909                 return false;
 910 
 911             }
 912 
 913             DOCINFOA di = new DOCINFOA();
 914 
 915             di.pDocName = "My C#.NET RAW Document";
 916 
 917             di.pDataType = "RAW";
 918 
 919             //Start a document.
 920 
 921             Boolean bl = StartDocPrinter(m_Handle, 1, di);
 922 
 923             if (!bl)
 924 
 925             {
 926 
 927                 return false;
 928 
 929             }
 930 
 931             // Start a page.
 932 
 933             bl = StartPagePrinter(m_Handle);
 934 
 935             return bl;
 936 
 937         }
 938 
 939  
 940 
 941         /// <summary>
 942 
 943         /// 结束打印,在打印结束之后必须调用此函数
 944 
 945         /// </summary>
 946 
 947         /// <returns></returns>
 948 
 949         public Boolean EndPrint()
 950 
 951         {
 952 
 953             if (!m_Inited)
 954 
 955             {
 956 
 957                 return false;
 958 
 959             }
 960 
 961             Boolean bl = EndPagePrinter(m_Handle);
 962 
 963             bl = EndDocPrinter(m_Handle);
 964 
 965             return bl;
 966 
 967         }
 968 
 969        
 970 
 971         /// <summary>
 972 
 973         /// 销毁
 974 
 975         /// </summary>
 976 
 977         /// <returns></returns>
 978 
 979         public Boolean Close()
 980 
 981         {
 982 
 983             if (!m_Inited)
 984 
 985             {
 986 
 987                 return true;
 988 
 989             }
 990 
 991             m_Inited = false;
 992 
 993  
 994 
 995             //关闭设备句柄
 996 
 997             ClosePrinter(m_Handle);
 998 
 999             m_Handle = -1;
1000 
1001             return true;
1002 
1003         }
1004 
1005        
1006 
1007         /// <summary>
1008 
1009         /// 打印文本.在调用本函数之前必须先调用正确的 设置字体、左边距
1010 
1011         /// </summary>
1012 
1013         /// <param name="content"></param>
1014 
1015         /// <returns></returns>
1016 
1017         public Boolean PrintText(String content)
1018 
1019         {
1020 
1021             if (!m_Inited)
1022 
1023             {
1024 
1025                 return false;
1026 
1027             }
1028 
1029  
1030 
1031             byte[] bytes = null;
1032 
1033             if (content.Length < 1)
1034 
1035             {
1036 
1037                 content =  "  ";
1038 
1039             }
1040 
1041            
1042 
1043             if (content[content.Length - 1] != (char)0x0D &&
1044 
1045                 content[content.Length - 1] != (char)0x0A)
1046 
1047             {
1048 
1049                 content = content + (char)0x0A;
1050 
1051             }
1052 
1053            
1054 
1055             bytes = DataFormatProcessor.StringToBytes(content);
1056 
1057             bool bl = SendCommand(bytes);
1058 
1059             return bl;
1060 
1061         }
1062 
1063  
1064 
1065         /// <summary>
1066 
1067         /// 设置对齐方式
1068 
1069         /// </summary>
1070 
1071         /// <param name="left"></param>
1072 
1073         /// <returns></returns>
1074 
1075         public bool SetAlignMode(eTextAlignMode alignmode)
1076 
1077         {
1078 
1079             if (!m_Inited)
1080 
1081             {
1082 
1083                 return false;
1084 
1085             }
1086 
1087  
1088 
1089             String code = String.Empty;
1090 
1091             switch (alignmode)
1092 
1093             {
1094 
1095                 case eTextAlignMode.Left:
1096 
1097                     code = Const_Align_Left;
1098 
1099                     break;
1100 
1101                 case eTextAlignMode.Middle:
1102 
1103                     code = Const_Align_Middle;
1104 
1105                     break;
1106 
1107                 case eTextAlignMode.Right:
1108 
1109                     code = Const_Align_Right;
1110 
1111                     break;
1112 
1113                 default:
1114 
1115                     code = Const_Align_Left;
1116 
1117                     break;
1118 
1119             }
1120 
1121  
1122 
1123             //注意:先低字节后高字节
1124 
1125             string str = Const_SetAlign + code;
1126 
1127             bool bl = SendCommand(str);
1128 
1129             return bl;
1130 
1131         }
1132 
1133        
1134 
1135         /// <summary>
1136 
1137         /// 设置左边距
1138 
1139         /// </summary>
1140 
1141         /// <param name="left"></param>
1142 
1143         /// <returns></returns>
1144 
1145         public bool SetLeft(int left)
1146 
1147         {
1148 
1149             if (!m_Inited)
1150 
1151             {
1152 
1153                 return false;
1154 
1155             }
1156 
1157  
1158 
1159             //注意:先低字节后高字节
1160 
1161             String hexstr = left.ToString("X4");
1162 
1163             string str = Const_SetLeft + hexstr.Substring(2, 2) + hexstr.Substring(0, 2);
1164 
1165             bool bl = SendCommand(str);
1166 
1167             return bl;
1168 
1169         }
1170 
1171  
1172 
1173         /// <summary>
1174 
1175         /// 设置粗体
1176 
1177         /// </summary>
1178 
1179         /// <param name="bold"></param>
1180 
1181         /// <returns></returns>
1182 
1183         public Boolean SetBold(Boolean bold)
1184 
1185         {
1186 
1187             if (!m_Inited)
1188 
1189             {
1190 
1191                 return false;
1192 
1193             }
1194 
1195  
1196 
1197             //注意:先低字节后高字节
1198 
1199             String str = String.Empty;
1200 
1201             if (bold)
1202 
1203             {
1204 
1205                 str = Const_SetBold + Const_Bold_YES;
1206 
1207             }
1208 
1209             else
1210 
1211             {
1212 
1213                 str = Const_SetBold + Const_Bold_NO;
1214 
1215             }
1216 
1217             bool bl = SendCommand(str);
1218 
1219             return bl;
1220 
1221         }
1222 
1223  
1224 
1225         /// <summary>
1226 
1227         /// 切纸
1228 
1229         /// </summary>
1230 
1231         /// <returns></returns>
1232 
1233         public bool Cut()
1234 
1235         {
1236 
1237             if (!m_Inited)
1238 
1239             {
1240 
1241                 return false;
1242 
1243             }
1244 
1245             bool bl = SendCommand(Const_SetCut);
1246 
1247             return bl;
1248 
1249         }
1250 
1251  
1252 
1253  
1254 
1255         /// <summary>
1256 
1257         /// 打印图片
1258 
1259         /// </summary>
1260 
1261         /// <param name="bitmap"></param>
1262 
1263         /// <returns></returns>
1264 
1265         public bool PrintImageFile(String imgfilename)
1266 
1267         {
1268 
1269             if (!m_Inited)
1270 
1271             {
1272 
1273                 return false;
1274 
1275             }
1276 
1277             Bitmap img = ImageProcessor.LoadBitImage(imgfilename);
1278 
1279             if (img == null)
1280 
1281             {
1282 
1283                 return false;
1284 
1285             }
1286 
1287  
1288 
1289             Boolean bl = PrintBitmap(img);
1290 
1291             return bl;
1292 
1293         }
1294 
1295        
1296 
1297         /// <summary>
1298 
1299         /// 打印图片
1300 
1301         /// </summary>
1302 
1303         /// <param name="bitmap"></param>
1304 
1305         /// <returns></returns>
1306 
1307         public bool PrintBitmap(Bitmap bitmap)
1308 
1309         {
1310 
1311             if (!m_Inited)
1312 
1313             {
1314 
1315                 return false;
1316 
1317             }
1318 
1319  
1320 
1321             if (bitmap == null ||
1322 
1323                 bitmap.Width > Const_MaxImageLength ||
1324 
1325                 bitmap.Height > Const_MaxImageLength)
1326 
1327             {
1328 
1329                 return false;
1330 
1331             }
1332 
1333  
1334 
1335             Byte[] bitary = null;
1336 
1337             Int32 width = 0;
1338 
1339             Int32 height = 0;
1340 
1341             Boolean bl = GetBitArray(bitmap, ref bitary, ref width, ref height);
1342 
1343  
1344 
1345             bl = PrintBitmapBytes(bitary, bitmap.Width, bitmap.Height);
1346 
1347             return bl;
1348 
1349         }
1350 
1351  
1352 
1353         /// <summary>
1354 
1355         /// 打印图片
1356 
1357         /// </summary>
1358 
1359         /// <param name="bitmap"></param>
1360 
1361         /// <returns></returns>
1362 
1363         public bool PrintBitmapBytes(Byte[] imgbitarray, Int32 width, Int32 height)
1364 
1365         {
1366 
1367             if (!m_Inited)
1368 
1369             {
1370 
1371                 return false;
1372 
1373             }
1374 
1375             Int32 bytes = width * height / 8;
1376 
1377             //检查是否尺寸符合要求
1378 
1379             if (width > Const_MaxImageLength || height > Const_MaxFeedLength ||
1380 
1381                 width < 1 || height < 1 ||
1382 
1383                 imgbitarray == null)
1384 
1385             {
1386 
1387                 return false;
1388 
1389             }
1390 
1391             
1392 
1393             //每次获取24行的数据进行发送,这24行的字节数
1394 
1395             Int32 blockbytes = width * Const_OncePrintRowCount / 8;
1396 
1397             if (blockbytes < 1)
1398 
1399             {
1400 
1401                 return false;
1402 
1403             }
1404 
1405  
1406 
1407             Boolean bl = false;
1408 
1409  
1410 
1411             //一共需要发送的块数量
1412 
1413             Int32 blocks = imgbitarray.Length / blockbytes;
1414 
1415  
1416 
1417             //每次发送的数据字节数 = 1B 2A 21 2字节长度 + 数据内容
1418 
1419             Byte[] cmdbytes = new Byte[5 + blockbytes];
1420 
1421             //指令
1422 
1423             Array.Copy(Const_SetImageCommand, cmdbytes, 3);
1424 
1425             //数据长度,即 每行的点数
1426 
1427             DataFormatProcessor.Int16ToBytes(width, ref cmdbytes, 3);
1428 
1429             //数据内容
1430 
1431             for (Int32 blockidx = 0; blockidx < blocks; ++blockidx)
1432 
1433             {
1434 
1435                 Array.Copy(imgbitarray, blockidx * blockbytes, cmdbytes, 5, blockbytes);
1436 
1437                 //发送当前指令
1438 
1439                 bl = SendCommand(cmdbytes);
1440 
1441                 if (!bl) return false;
1442 
1443                 //休眠20毫秒
1444 
1445                 Thread.Sleep(20);
1446 
1447                 //发送 打印指令
1448 
1449                 bl = SendCommand(Const_Cmd_Print);
1450 
1451                 if (!bl) return false;
1452 
1453             }
1454 
1455  
1456 
1457             return bl;
1458 
1459         }
1460 
1461  
1462 
1463         /// <summary>
1464 
1465         /// 走纸
1466 
1467         /// </summary>
1468 
1469         /// <param name="length"></param>
1470 
1471         /// <returns></returns>
1472 
1473         public bool Feed(int length)
1474 
1475         {
1476 
1477             if (!m_Inited)
1478 
1479             {
1480 
1481                 return false;
1482 
1483             }
1484 
1485             if (length < 1)
1486 
1487                 length = 1;
1488 
1489             if (length > Const_MaxFeedLength)
1490 
1491             {
1492 
1493                 length = Const_MaxFeedLength;
1494 
1495             }
1496 
1497             string len = length.ToString("X2");
1498 
1499             len = Const_FeedForward + len;
1500 
1501             bool bl = SendCommand(len);
1502 
1503             return bl;
1504 
1505         }
1506 
1507  
1508 
1509         /// <summary>
1510 
1511         /// 回退走纸
1512 
1513         /// </summary>
1514 
1515         /// <param name="length"></param>
1516 
1517         /// <returns></returns>
1518 
1519         public bool FeedBack(int length)
1520 
1521         {
1522 
1523             if (!m_Inited)
1524 
1525             {
1526 
1527                 return false;
1528 
1529             }
1530 
1531             if (length < 1)
1532 
1533                 length = 1;
1534 
1535             if (length > Const_MaxFeedLength)
1536 
1537             {
1538 
1539                 length = Const_MaxFeedLength;
1540 
1541             }
1542 
1543             string len = length.ToString("X2");
1544 
1545             len = Const_FeedBack + len;
1546 
1547             bool bl = SendCommand(len);
1548 
1549             return bl;
1550 
1551         }
1552 
1553        
1554 
1555         /// <summary>
1556 
1557         /// 设置字体大小.本函数不可与SetBigFont同时使用
1558 
1559         /// </summary>
1560 
1561         /// <param name="sizerate">大小倍率,取值范围 1 - 8</param>
1562 
1563         /// <returns></returns>
1564 
1565         public bool SetFontSize(Int32 sizerate)
1566 
1567         {
1568 
1569             if (!m_Inited)
1570 
1571             {
1572 
1573                 return false;
1574 
1575             }
1576 
1577            
1578 
1579             if (sizerate < 1)
1580 
1581             {
1582 
1583                 sizerate = 1;
1584 
1585             }
1586 
1587  
1588 
1589             if (sizerate > Const_MaxFontSize)
1590 
1591             {
1592 
1593                 sizerate = Const_MaxFontSize;
1594 
1595             }
1596 
1597             sizerate--;
1598 
1599             String sizecodestr = Const_SetFontSize + sizerate.ToString("X1") + sizerate.ToString("X1");
1600 
1601             bool bl = SendCommand(sizecodestr);
1602 
1603             return bl;
1604 
1605         }
1606 
1607  
1608 
1609         #endregion
1610 
1611  
1612 
1613         
1614 
1615  
1616 
1617     }
1618 
1619 }
1620 
1621  
1622 
1623 3.图像处理 ImageProcessor
1624 using System;
1625 
1626 using System.Collections.Generic;
1627 
1628 using System.Linq;
1629 
1630 using System.Text;
1631 
1632 using System.Drawing;
1633 
1634 using LaisonTech.CommonBLL;
1635 
1636 using System.Drawing.Imaging;
1637 
1638 using System.IO;
1639 
1640 using System.Drawing.Drawing2D;
1641 
1642 using System.Windows.Forms;
1643 
1644 using AForge.Imaging.Filters;
1645 
1646  
1647 
1648 namespace LaisonTech.MediaLib
1649 
1650 {
1651 
1652     /// <summary>
1653 
1654     /// 图片格式
1655 
1656     /// </summary>
1657 
1658     public enum ePictureFileFormat
1659 
1660     {
1661 
1662         Bmp = 0,
1663 
1664         Gif = 1,
1665 
1666         Icon = 2,
1667 
1668         Jpeg = 3,
1669 
1670         Png = 4,
1671 
1672     }
1673 
1674  
1675 
1676     /// <summary>
1677 
1678     /// 转为灰度图像的方式
1679 
1680     /// </summary>
1681 
1682     public enum eGrayMode
1683 
1684     {
1685 
1686         /// <summary>
1687 
1688         /// 算数平均
1689 
1690         /// </summary>
1691 
1692         ArithmeticAverage = 0,
1693 
1694         /// <summary>
1695 
1696         /// 加权平均
1697 
1698         /// </summary>
1699 
1700         WeightedAverage = 1,
1701 
1702     }
1703 
1704  
1705 
1706     /// <summary>
1707 
1708     /// 比较2个图片的指定区域范围,像素的相同类型
1709 
1710     /// </summary>
1711 
1712     public enum eAreaDifferentType
1713 
1714     {
1715 
1716         /// <summary>
1717 
1718         /// 所有像素都相同
1719 
1720         /// </summary>
1721 
1722         AllSame = 0,
1723 
1724         /// <summary>
1725 
1726         /// 所有像素都不同
1727 
1728         /// </summary>
1729 
1730         AllDifferent = 1,
1731 
1732         /// <summary>
1733 
1734         /// 部分相同部分不同
1735 
1736         /// </summary>
1737 
1738         Partial = 2,
1739 
1740     }
1741 
1742  
1743 
1744     /// <summary>
1745 
1746     /// 图片文件处理
1747 
1748     /// </summary>
1749 
1750     public class ImageProcessor
1751 
1752     {
1753 
1754         #region 常量定义
1755 
1756  
1757 
1758         public const Byte Const_BrightnessWhite = 255;
1759 
1760         public const Byte Const_BrightnessBlack = 0;
1761 
1762  
1763 
1764  
1765 
1766         /// <summary>
1767 
1768         /// 比较结果的图片里,亮度相同部分的填充颜色
1769 
1770         /// </summary>
1771 
1772         public static Color Const_SameBrightnessColor = Color.Black;
1773 
1774         /// <summary>
1775 
1776         /// 比较结果的图片里,亮度相同部分的填充颜色
1777 
1778         /// </summary>
1779 
1780         public static Color Const_DifferentBrightnessColor = Color.White;
1781 
1782  
1783 
1784         public const Byte Const_BlackBrightness = 0;
1785 
1786         public const Byte Const_WhiteBrightness = 255;
1787 
1788         public const Int32 Const_MaxBrightness = 255;
1789 
1790  
1791 
1792         public const Int32 Const_MinBrightness = -255;
1793 
1794  
1795 
1796         /// <summary>
1797 
1798         /// 亮度的中间值
1799 
1800         /// </summary>
1801 
1802         public const Int32 Const_MiddleBrightness = 128;
1803 
1804         #endregion
1805 
1806  
1807 
1808         #region 屏幕截图,打印
1809 
1810  
1811 
1812         /// <summary>
1813 
1814         /// 获取屏幕分辨率
1815 
1816         /// </summary>
1817 
1818         /// <param name="width"></param>
1819 
1820         /// <param name="height"></param>
1821 
1822         public static void GetScreenSize(ref Int32 width, ref Int32 height)
1823 
1824         {
1825 
1826             height = Screen.PrimaryScreen.Bounds.Height;
1827 
1828             width = Screen.PrimaryScreen.Bounds.Width;
1829 
1830         }
1831 
1832  
1833 
1834         /// <summary>
1835 
1836         ///截图指定控件上显示的内容
1837 
1838         /// </summary>
1839 
1840         /// <param name="ctrl"></param>
1841 
1842         /// <returns></returns>
1843 
1844         public static Image CaptureControlImage(Control ctrl)
1845 
1846         {
1847 
1848             if (ctrl == null)
1849 
1850             {
1851 
1852                 return null;
1853 
1854             }
1855 
1856  
1857 
1858             Control parent = ctrl;
1859 
1860             if (ctrl.Parent != null)
1861 
1862             {
1863 
1864                 parent = ctrl.Parent;
1865 
1866             }
1867 
1868             Point screenPoint = parent.PointToScreen(ctrl.Location);
1869 
1870  
1871 
1872             Image ret = new Bitmap(ctrl.Width, ctrl.Height);
1873 
1874             Graphics g = Graphics.FromImage(ret);
1875 
1876             g.CopyFromScreen(screenPoint.X, screenPoint.Y,
1877 
1878                 0, 0, ctrl.Size);
1879 
1880             g.DrawImage(ret, 0, 0);
1881 
1882  
1883 
1884             return ret;
1885 
1886         }
1887 
1888  
1889 
1890  
1891 
1892         #endregion
1893 
1894  
1895 
1896         #region 装载图片
1897 
1898  
1899 
1900         /// <summary>
1901 
1902         /// 装载图像文件
1903 
1904         /// </summary>
1905 
1906         /// <param name="filename"></param>
1907 
1908         /// <returns></returns>
1909 
1910         public static Image LoadImage(String filename)
1911 
1912         {
1913 
1914             //Boolean bl = FileProcessor.FileExist(filename);
1915 
1916             //if (!bl)
1917 
1918             //{
1919 
1920             //    return null;
1921 
1922             //}
1923 
1924             //Bitmap image = (Bitmap)Bitmap.FromFile(filename);
1925 
1926             //return image;
1927 
1928  
1929 
1930             //以上方法会导致图片文件被锁定,无法删除移动
1931 
1932  
1933 
1934             Byte[] photodata = null;
1935 
1936             Boolean bl = FileProcessor.FileExist(filename);
1937 
1938             if (!bl)
1939 
1940             {
1941 
1942                 return null;
1943 
1944             }
1945 
1946  
1947 
1948             bl = FileProcessor.ReadFileBytes(filename, out photodata);
1949 
1950             if (!bl)
1951 
1952             {
1953 
1954                 return null;
1955 
1956             }
1957 
1958  
1959 
1960             MemoryStream ms = null;
1961 
1962             Image myImage = null;
1963 
1964             try
1965 
1966             {
1967 
1968                 ms = new MemoryStream(photodata);
1969 
1970                 myImage = Bitmap.FromStream(ms);
1971 
1972                 ms.Close();
1973 
1974             }
1975 
1976             catch (System.Exception ex)
1977 
1978             {
1979 
1980                 Console.WriteLine("LoadImage error:" + ex.Message);
1981 
1982                 myImage = null;
1983 
1984             }
1985 
1986             return myImage;
1987 
1988         }
1989 
1990  
1991 
1992         /// <summary>
1993 
1994         /// 装载图像文件
1995 
1996         /// </summary>
1997 
1998         /// <param name="filename"></param>
1999 
2000         /// <returns></returns>
2001 
2002         public static Bitmap LoadBitImage(String filename)
2003 
2004         {
2005 
2006             Bitmap ret = (Bitmap)LoadImage(filename);
2007 
2008             return ret;
2009 
2010         }
2011 
2012  
2013 
2014         /// <summary>
2015 
2016         /// 保存图片到指定路径
2017 
2018         /// </summary>
2019 
2020         /// <param name="img"></param>
2021 
2022         /// <param name="filename"></param>
2023 
2024         /// <returns></returns>
2025 
2026         public static Boolean SaveImage(Image img, String filename)
2027 
2028         {
2029 
2030             FileProcessor.DeleteFile(filename);
2031 
2032             if (img == null)
2033 
2034             {
2035 
2036                 return false;
2037 
2038             }
2039 
2040             //获取保存图片的路径,如果路径不存在,新建
2041 
2042             String folder = FileProcessor.GetDirectoryName(filename);
2043 
2044             if (!FileProcessor.DirectoryExist(folder))
2045 
2046             {
2047 
2048                 FileProcessor.CreateDirectory(folder);
2049 
2050             }
2051 
2052             img.Save(filename);
2053 
2054             Boolean bl = FileProcessor.FileExist(filename);
2055 
2056             return bl;
2057 
2058         }
2059 
2060  
2061 
2062         #endregion
2063 
2064        
2065 
2066         #region 转换图片格式
2067 
2068        
2069 
2070         /// <summary>
2071 
2072         /// 转换图片格式
2073 
2074         /// </summary>
2075 
2076         /// <param name="bmpfilename"></param>
2077 
2078         /// <param name="jpgfilename"></param>
2079 
2080         /// <returns></returns>
2081 
2082         public static Boolean BmpToJpg(String bmpfilename, String jpgfilename)
2083 
2084         {
2085 
2086             Boolean bl = ChangeFileFormat(bmpfilename, jpgfilename, ePictureFileFormat.Jpeg);
2087 
2088             return bl;
2089 
2090         }
2091 
2092  
2093 
2094         /// <summary>
2095 
2096         /// 转换图片格式
2097 
2098         /// </summary>
2099 
2100         /// <param name="srcfilename"></param>
2101 
2102         /// <param name="destfilename"></param>
2103 
2104         /// <param name="destformat"></param>
2105 
2106         /// <returns></returns>
2107 
2108         public static Boolean ChangeFileFormat(String srcfilename, String destfilename, ePictureFileFormat destformat)
2109 
2110         {
2111 
2112             Boolean bl = FileProcessor.FileExist(srcfilename);
2113 
2114             if (!bl)
2115 
2116             {
2117 
2118                 return false;
2119 
2120             }
2121 
2122             Image image = Image.FromFile(srcfilename);
2123 
2124  
2125 
2126             ImageFormat IFMT = null;
2127 
2128             switch (destformat)
2129 
2130             {
2131 
2132                 case ePictureFileFormat.Bmp:
2133 
2134                     IFMT = ImageFormat.Bmp;
2135 
2136                     break;
2137 
2138                 case ePictureFileFormat.Gif:
2139 
2140                     IFMT = ImageFormat.Gif;
2141 
2142                     break;
2143 
2144                 case ePictureFileFormat.Icon:
2145 
2146                     IFMT = ImageFormat.Icon;
2147 
2148                     break;
2149 
2150                 case ePictureFileFormat.Jpeg:
2151 
2152                     IFMT = ImageFormat.Jpeg;
2153 
2154                     break;
2155 
2156                 case ePictureFileFormat.Png:
2157 
2158                     IFMT = ImageFormat.Png;
2159 
2160                     break;
2161 
2162                 default:
2163 
2164                     IFMT = ImageFormat.Jpeg;
2165 
2166                     break;
2167 
2168             }
2169 
2170             image.Save(destfilename, IFMT);
2171 
2172             image.Dispose();
2173 
2174  
2175 
2176             bl = FileProcessor.FileExist(destfilename);
2177 
2178             if (!bl)
2179 
2180             {
2181 
2182                 return false;
2183 
2184             }
2185 
2186  
2187 
2188             Int32 filelen = FileProcessor.GetFileLength(destfilename);
2189 
2190             return (filelen > 0);
2191 
2192         }
2193 
2194  
2195 
2196         /// <summary>
2197 
2198         /// 变成黑白图
2199 
2200         /// </summary>
2201 
2202         /// <param name="srcbitmap">原始图</param>
2203 
2204         /// <param name="mode">模式。0:加权平均  1:算数平均</param>
2205 
2206         /// <returns></returns>
2207 
2208         public static Bitmap ToGray(Bitmap bitmap, eGrayMode mode = eGrayMode.ArithmeticAverage)
2209 
2210         {
2211 
2212             if (bitmap == null)
2213 
2214             {
2215 
2216                 return null;
2217 
2218             }
2219 
2220  
2221 
2222             int width = bitmap.Width;
2223 
2224             int height = bitmap.Height;
2225 
2226             byte newColor = 0;
2227 
2228             try
2229 
2230             {
2231 
2232                 BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),
2233 
2234                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
2235 
2236                 unsafe
2237 
2238                 {
2239 
2240                     byte* curpix = (byte*)srcData.Scan0.ToPointer();
2241 
2242                     if (mode == eGrayMode.ArithmeticAverage)// 算数平均
2243 
2244                     {
2245 
2246                         for (int y = 0; y < height; y++)
2247 
2248                         {
2249 
2250                             for (int x = 0; x < width; x++)
2251 
2252                             {
2253 
2254                                 newColor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);
2255 
2256                                 curpix[0] = newColor;
2257 
2258                                 curpix[1] = newColor;
2259 
2260                                 curpix[2] = newColor;
2261 
2262                                 curpix += 3;
2263 
2264                             }
2265 
2266                             curpix += srcData.Stride - width * 3;
2267 
2268                         }
2269 
2270                     }
2271 
2272                     else
2273 
2274                     {
2275 
2276                         // 加权平均
2277 
2278                         for (int y = 0; y < height; y++)
2279 
2280                         {
2281 
2282                             for (int x = 0; x < width; x++)
2283 
2284                             {
2285 
2286                                 newColor = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);
2287 
2288                                 curpix[0] = newColor;
2289 
2290                                 curpix[1] = newColor;
2291 
2292                                 curpix[2] = newColor;
2293 
2294                                 curpix += 3;
2295 
2296                             }
2297 
2298                             curpix += srcData.Stride - width * 3;
2299 
2300                         }
2301 
2302                     }
2303 
2304                     bitmap.UnlockBits(srcData);
2305 
2306                 }
2307 
2308             }
2309 
2310             catch
2311 
2312             {
2313 
2314                 bitmap = null;
2315 
2316             }
2317 
2318  
2319 
2320             return bitmap;
2321 
2322         }
2323 
2324  
2325 
2326         /// <summary>
2327 
2328         /// 获取一幅图片对应的所有像素亮度数组
2329 
2330         /// </summary>
2331 
2332         /// <param name="bitmap">原始图</param>
2333 
2334         /// <param name="brightnessary">亮度值数组</param>
2335 
2336         /// <param name="mode">模式。0:加权平均  1:算数平均</param>
2337 
2338         /// <returns></returns>
2339 
2340         public static Boolean GetImageBrightness(Bitmap bitmap, ref Byte[] brightnessary,
2341 
2342             eGrayMode mode = eGrayMode.WeightedAverage)
2343 
2344         {
2345 
2346             if (bitmap == null)
2347 
2348             {
2349 
2350                 return false;
2351 
2352             }
2353 
2354  
2355 
2356             int width = bitmap.Width;
2357 
2358             int height = bitmap.Height;
2359 
2360             if (width < 1 || height < 1)
2361 
2362             {
2363 
2364                 return false;
2365 
2366             }
2367 
2368             
2369 
2370             brightnessary = new Byte[width * height];
2371 
2372             Boolean bl = false;
2373 
2374             Int32 rowredundancy = 0;//每一行像素,对应的数组长度 与 实际像素点数的差值
2375 
2376             Int32 pixidx = 0;//像素下标
2377 
2378             try
2379 
2380             {
2381 
2382                 BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),
2383 
2384                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
2385 
2386                 rowredundancy = srcData.Stride - width * 3;//每行末尾还有这么多的冗余字节
2387 
2388  
2389 
2390                 unsafe
2391 
2392                 {
2393 
2394                     byte* curpix = (byte*)srcData.Scan0.ToPointer();
2395 
2396                     if (mode == eGrayMode.ArithmeticAverage)// 算数平均
2397 
2398                     {
2399 
2400                         for (int y = 0; y < height; y++)
2401 
2402                         {
2403 
2404                             for (int x = 0; x < width; x++)
2405 
2406                             {
2407 
2408                                 brightnessary[pixidx] = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);
2409 
2410                                 ++pixidx;
2411 
2412                                 curpix += 3;
2413 
2414                             }
2415 
2416                             curpix += rowredundancy;
2417 
2418                         }
2419 
2420                     }
2421 
2422                     else
2423 
2424                     {
2425 
2426                         // 加权平均
2427 
2428                         for (int y = 0; y < height; y++)
2429 
2430                         {
2431 
2432                             for (int x = 0; x < width; x++)
2433 
2434                             {
2435 
2436                                 brightnessary[pixidx] = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);
2437 
2438                                 ++pixidx;
2439 
2440                                 curpix += 3;
2441 
2442                             }
2443 
2444                             curpix += rowredundancy;
2445 
2446                         }
2447 
2448                     }
2449 
2450                     bitmap.UnlockBits(srcData);
2451 
2452                 }
2453 
2454                 bl = true;
2455 
2456             }
2457 
2458             catch(Exception ex)
2459 
2460             {
2461 
2462                 bl = false;
2463 
2464                 Console.WriteLine("Get brightness ary error:" + ex.Message);
2465 
2466             }
2467 
2468  
2469 
2470             return bl;
2471 
2472         }
2473 
2474  
2475 
2476         /// <summary>
2477 
2478         /// 变成黑白图,每个元素都是一个像素的亮度
2479 
2480         /// </summary>
2481 
2482         /// <param name=" bitmap ">原始图</param>
2483 
2484         /// <param name=" graybitmap ">黑白图</param>
2485 
2486         /// <param name=" brightnessbytes ">黑白所有像素点亮度</param>
2487 
2488         /// <param name="mode">模式。0:加权平均  1:算数平均</param>
2489 
2490         /// <returns></returns>
2491 
2492         public static Boolean ToGray(Bitmap bitmap, ref Bitmap graybitmap, ref Byte[] brightnessbytes,
2493 
2494             eGrayMode mode = eGrayMode.WeightedAverage)
2495 
2496         {
2497 
2498             if (bitmap == null)
2499 
2500             {
2501 
2502                 return false;
2503 
2504             }
2505 
2506  
2507 
2508             brightnessbytes = new Byte[bitmap.Width * bitmap.Height];
2509 
2510  
2511 
2512             int width = bitmap.Width;
2513 
2514             int height = bitmap.Height;
2515 
2516             //Clone 可能引发 GDI+异常
2517 
2518             graybitmap = new Bitmap(bitmap);
2519 
2520          
2521 
2522             byte newColor = 0;
2523 
2524             Int32 bytesidx = 0;
2525 
2526             Boolean bl = false;
2527 
2528             try
2529 
2530             {
2531 
2532                 BitmapData srcData = graybitmap.LockBits(new Rectangle(0, 0, width, height),
2533 
2534                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
2535 
2536                 unsafe
2537 
2538                 {
2539 
2540                     byte* curpix = (byte*)srcData.Scan0.ToPointer();
2541 
2542                     if (mode == eGrayMode.ArithmeticAverage)// 算数平均
2543 
2544                     {
2545 
2546                         for (int y = 0; y < height; y++)
2547 
2548                         {
2549 
2550                             for (int x = 0; x < width; x++)
2551 
2552                             {
2553 
2554                                 newColor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);
2555 
2556                                
2557 
2558                                 brightnessbytes[bytesidx] = newColor;
2559 
2560                                 ++bytesidx;
2561 
2562  
2563 
2564                                 curpix[0] = newColor;
2565 
2566                                 curpix[1] = newColor;
2567 
2568                                 curpix[2] = newColor;
2569 
2570                                 curpix += 3;
2571 
2572                             }
2573 
2574                             curpix += srcData.Stride - width * 3;
2575 
2576                         }
2577 
2578                     }
2579 
2580                     else
2581 
2582                     {
2583 
2584                         // 加权平均
2585 
2586                         for (int y = 0; y < height; y++)
2587 
2588                         {
2589 
2590                             for (int x = 0; x < width; x++)
2591 
2592                             {
2593 
2594                                 newColor = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);
2595 
2596  
2597 
2598                                 brightnessbytes[bytesidx] = newColor;
2599 
2600                                 ++bytesidx;
2601 
2602                                
2603 
2604                                 curpix[0] = newColor;
2605 
2606                                 curpix[1] = newColor;
2607 
2608                                 curpix[2] = newColor;
2609 
2610                                 curpix += 3;
2611 
2612                             }
2613 
2614                             curpix += srcData.Stride - width * 3;
2615 
2616                         }
2617 
2618                     }
2619 
2620                     graybitmap.UnlockBits(srcData);
2621 
2622                 }
2623 
2624  
2625 
2626                 bl = true;
2627 
2628             }
2629 
2630             catch(Exception ex)
2631 
2632             {
2633 
2634                 graybitmap = null;
2635 
2636                 Console.WriteLine("ToGray error:" + ex.Message);
2637 
2638                 bl = false;
2639 
2640             }
2641 
2642  
2643 
2644             return bl;
2645 
2646         }
2647 
2648  
2649 
2650        
2651 
2652         /// <summary>
2653 
2654         /// 把图片转换为非黑即白的二色图.
2655 
2656         /// </summary>
2657 
2658         /// <param name="bitmap">原始图</param>
2659 
2660         /// <param name="brightnessGate">亮度门限.超过此亮度认为白点,否则认为黑点</param>
2661 
2662         /// <param name="bitary">每个像素点是否为黑点的数组</param>
2663 
2664         /// <param name="trueAsblack">true-每个元素黑点为true,白点为false; false-每个元素白点为true,黑点为false</param>
2665 
2666         /// <returns></returns>
2667 
2668         public static Boolean ToBooleanArray(Bitmap bitmap, Byte brightnessGate, ref Boolean[] bitary, Boolean trueAsblack = true)
2669 
2670         {
2671 
2672             if (bitmap == null)
2673 
2674             {
2675 
2676                 return false;
2677 
2678             }
2679 
2680  
2681 
2682             bitary = new Boolean[bitmap.Width * bitmap.Height];
2683 
2684  
2685 
2686             int width = bitmap.Width;
2687 
2688             int height = bitmap.Height;
2689 
2690  
2691 
2692             byte curcolor = 0;
2693 
2694             Int32 pixidx = 0;
2695 
2696             Boolean bl = false;
2697 
2698             try
2699 
2700             {
2701 
2702                 BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),
2703 
2704                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
2705 
2706                 unsafe
2707 
2708                 {
2709 
2710                     byte* curpix = (byte*)srcData.Scan0.ToPointer();
2711 
2712  
2713 
2714                     for (int y = 0; y < height; y++)
2715 
2716                     {
2717 
2718                         for (int x = 0; x < width; x++)
2719 
2720                         {
2721 
2722                             curcolor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);
2723 
2724  
2725 
2726                             if (trueAsblack)//true为黑点
2727 
2728                             {
2729 
2730                                 bitary[pixidx] = (curcolor < brightnessGate);
2731 
2732                             }
2733 
2734                             else
2735 
2736                             {
2737 
2738                                 //true为白点
2739 
2740                                 bitary[pixidx] = (curcolor > brightnessGate);
2741 
2742                             }
2743 
2744                             ++pixidx;                            
2745 
2746                             curpix += 3;
2747 
2748                         }
2749 
2750                         curpix += srcData.Stride - width * 3;
2751 
2752                     }
2753 
2754                     bitmap.UnlockBits(srcData);
2755 
2756                 }
2757 
2758  
2759 
2760                 bl = true;
2761 
2762             }
2763 
2764             catch (Exception ex)
2765 
2766             {
2767 
2768                 Console.WriteLine("ToGray error:" + ex.Message);
2769 
2770                 bl = false;
2771 
2772             }
2773 
2774  
2775 
2776             return bl;
2777 
2778         }
2779 
2780  
2781 
2782         /// <summary>
2783 
2784         /// 亮度差数组变成bool数组.true表示亮度不同,false表示亮度相同
2785 
2786         /// </summary>
2787 
2788         /// <param name="bridiffary">亮度差数组</param>
2789 
2790         /// <param name="brightnessGate">亮度门限.超过此亮度认为白点,否则认为黑点</param>
2791 
2792         /// <returns></returns>
2793 
2794         public static Boolean BrightnessToBoolean(Byte[] bridiffary, Byte brightnessGate, ref Boolean[] boolary)
2795 
2796         {
2797 
2798             if (bridiffary == null || bridiffary.Length < 4)
2799 
2800             {
2801 
2802                 return false;
2803 
2804             }
2805 
2806  
2807 
2808             boolary = new Boolean[bridiffary.Length];
2809 
2810  
2811 
2812             for (Int32 idx = 0; idx < bridiffary.Length; ++idx)
2813 
2814             {
2815 
2816                 boolary[idx] = (bridiffary[idx] > brightnessGate);
2817 
2818             }
2819 
2820  
2821 
2822             return true;
2823 
2824         }
2825 
2826  
2827 
2828         #endregion
2829 
2830  
2831 
2832         #region 图片调整
2833 
2834        
2835 
2836         /// <summary>
2837 
2838         /// 调整亮度
2839 
2840         /// </summary>
2841 
2842         /// <param name="bitmap">原始图</param>
2843 
2844         /// <param name="degree">亮度,取值范围-255 - 255</param>
2845 
2846         /// <returns></returns>
2847 
2848         public static Bitmap SetBrightness(Bitmap srcbitmap, int brightnessOffset)
2849 
2850         {
2851 
2852             if (srcbitmap == null)
2853 
2854             {
2855 
2856                 return null;
2857 
2858             }
2859 
2860  
2861 
2862             CommonCompute.SetInt32Range(ref brightnessOffset, Const_MinBrightness, Const_MaxBrightness);
2863 
2864             int width = srcbitmap.Width;
2865 
2866             int height = srcbitmap.Height;
2867 
2868  
2869 
2870             Bitmap bitmap = (Bitmap)srcbitmap.Clone();
2871 
2872  
2873 
2874             try
2875 
2876             {
2877 
2878                 BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height),
2879 
2880                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
2881 
2882  
2883 
2884                 unsafe
2885 
2886                 {
2887 
2888                     byte* curpix = (byte*)data.Scan0.ToPointer();
2889 
2890                     Int32 curcolor = 0;
2891 
2892                     for (int y = 0; y < height; y++)
2893 
2894                     {
2895 
2896                         for (int x = 0; x < width; x++)
2897 
2898                         {
2899 
2900                             curcolor = curpix[0] + brightnessOffset;
2901 
2902                             CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);
2903 
2904                             curpix[0] = (byte)curcolor;
2905 
2906  
2907 
2908                             curcolor = curpix[1] + brightnessOffset;
2909 
2910                             CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);
2911 
2912                             curpix[1] = (byte)curcolor;
2913 
2914  
2915 
2916                             curcolor = curpix[2] + brightnessOffset;
2917 
2918                             CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);
2919 
2920                             curpix[2] = (byte)curcolor;
2921 
2922  
2923 
2924                             curpix += 3;
2925 
2926                         }
2927 
2928                         curpix += data.Stride - width * 3;
2929 
2930                     }
2931 
2932                 }
2933 
2934  
2935 
2936                 bitmap.UnlockBits(data);
2937 
2938             }
2939 
2940             catch
2941 
2942             {
2943 
2944                 bitmap = null;
2945 
2946             }
2947 
2948  
2949 
2950             return bitmap;
2951 
2952         }
2953 
2954  
2955 
2956         /// <summary>
2957 
2958         /// 调整图像对比度
2959 
2960         /// </summary>
2961 
2962         /// <param name="bitmap">原始图</param>
2963 
2964         /// <param name="degree">对比度 0 - 100</param>
2965 
2966         /// <returns></returns>
2967 
2968         public static Bitmap SetContrast(Bitmap srcbitmap, int contrast)
2969 
2970         {
2971 
2972             if (srcbitmap == null)
2973 
2974             {
2975 
2976                 return null;
2977 
2978             }
2979 
2980  
2981 
2982             //对比度取值范围,0-100
2983 
2984             CommonCompute.SetInt32Range(ref contrast, 0, 100);
2985 
2986  
2987 
2988             Int32 curcolor = 0;
2989 
2990             Bitmap bitmap = (Bitmap)srcbitmap.Clone();
2991 
2992             int width = bitmap.Width;
2993 
2994             int height = bitmap.Height;
2995 
2996  
2997 
2998             //调整对比度基本思路:0时,所有像素点的亮度都设置为中间值128
2999 
3000             //100 时,把亮度大于128的像素,亮度设置为255;小于128的设置为0
3001 
3002             //即:50时,保持不变;小于50,所有点的亮度向中间值128偏移;大于50,所有点亮度值向两端偏移
3003 
3004  
3005 
3006             //如果当前像素点的亮度是130, 对比度为50时,结果仍然要是130,此时rate为1.0
3007 
3008             //对比度为100时,结果要变成255,此时rate >= 128
3009 
3010             //对比度为0时,结果要变成128,此时rate = 0
3011 
3012             //因此可知对比度与rate的对应关系
3013 
3014             //对比度:  0  50  100
3015 
3016             //rate  :  0  1   127              
3017 
3018             double rate = 0;
3019 
3020             if (contrast == 50)
3021 
3022             {
3023 
3024                 rate = 1;
3025 
3026             }
3027 
3028             else if (contrast < 50)
3029 
3030             {
3031 
3032                 rate = contrast / 50.0;//小于50的,对比度比率必须是纯小数,0-1 之间
3033 
3034             }
3035 
3036             else
3037 
3038             {
3039 
3040                 rate = 1 + Const_MiddleBrightness * ((contrast - 50.0) / 50.0);//大于50的,比率必须是1到128之间的值
3041 
3042             }
3043 
3044  
3045 
3046             try
3047 
3048             {
3049 
3050  
3051 
3052                 BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height),
3053 
3054                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
3055 
3056                 unsafe
3057 
3058                 {
3059 
3060                     byte* curpix = (byte*)data.Scan0.ToPointer();
3061 
3062  
3063 
3064                     for (int y = 0; y < height; y++)
3065 
3066                     {
3067 
3068                         for (int x = 0; x < width; x++)
3069 
3070                         {
3071 
3072                             for (int i = 0; i < 3; i++) //R,G,B 3个通道
3073 
3074                             {
3075 
3076                                 //对于 刚好亮度等于中间值的点,需要把亮度调高或调低1
3077 
3078                                 //否则将无法实现对该点 提高对比度
3079 
3080                                 if (curpix[i] == Const_MiddleBrightness)
3081 
3082                                 {
3083 
3084                                     curpix[i] = (byte)(curpix[i] + 1);
3085 
3086                                 }
3087 
3088  
3089 
3090                                 //调整该像素对比度
3091 
3092                                 curcolor = (Int32)(Const_MiddleBrightness + (curpix[i] - Const_MiddleBrightness) * rate);
3093 
3094                                 CommonCompute.SetInt32Range(ref curcolor, Const_MinBrightness, Const_MaxBrightness);
3095 
3096                                 curpix[i] = (byte)curcolor;
3097 
3098                                 ++curpix;
3099 
3100                             }
3101 
3102                         }
3103 
3104  
3105 
3106                         curpix += data.Stride - width * 3;
3107 
3108                     }
3109 
3110                 }
3111 
3112                 bitmap.UnlockBits(data);
3113 
3114             }
3115 
3116             catch
3117 
3118             {
3119 
3120                 bitmap = null;
3121 
3122             }
3123 
3124  
3125 
3126             return bitmap;
3127 
3128         }
3129 
3130  
3131 
3132         /// <summary>
3133 
3134         /// 任意角度旋转
3135 
3136         /// </summary>
3137 
3138         /// <param name="srcbitmap">原始图Bitmap</param>
3139 
3140         /// <param name="angle">旋转角度</param>
3141 
3142         /// <param name="bkColor">背景色</param>
3143 
3144         /// <returns>输出Bitmap</returns>
3145 
3146         public static Bitmap Rotate(Bitmap srcbitmap, float angle, Color bkColor)
3147 
3148         {
3149 
3150             int w = srcbitmap.Width + 2;
3151 
3152             int h = srcbitmap.Height + 2;
3153 
3154  
3155 
3156             PixelFormat pf;
3157 
3158  
3159 
3160             if (bkColor == Color.Transparent)
3161 
3162             {
3163 
3164                 pf = PixelFormat.Format32bppArgb;
3165 
3166             }
3167 
3168             else
3169 
3170             {
3171 
3172                 pf = srcbitmap.PixelFormat;
3173 
3174             }
3175 
3176  
3177 
3178             Bitmap tmp = new Bitmap(w, h, pf);
3179 
3180             Graphics g = Graphics.FromImage(tmp);
3181 
3182             g.Clear(bkColor);
3183 
3184             g.DrawImageUnscaled(srcbitmap, 1, 1);
3185 
3186             g.Dispose();
3187 
3188  
3189 
3190             GraphicsPath path = new GraphicsPath();
3191 
3192             path.AddRectangle(new RectangleF(0f, 0f, w, h));
3193 
3194             Matrix mtrx = new Matrix();
3195 
3196             mtrx.Rotate(angle);
3197 
3198             RectangleF rct = path.GetBounds(mtrx);
3199 
3200  
3201 
3202             Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
3203 
3204             g = Graphics.FromImage(dst);
3205 
3206             g.Clear(bkColor);
3207 
3208             g.TranslateTransform(-rct.X, -rct.Y);
3209 
3210             g.RotateTransform(angle);
3211 
3212             g.InterpolationMode = InterpolationMode.HighQualityBilinear;
3213 
3214             g.DrawImageUnscaled(tmp, 0, 0);
3215 
3216             g.Dispose();
3217 
3218  
3219 
3220             tmp.Dispose();
3221 
3222  
3223 
3224             return dst;
3225 
3226         }
3227 
3228  
3229 
3230         /// <summary>
3231 
3232         /// Gamma校正
3233 
3234         /// </summary>
3235 
3236         /// <param name="srcbitmap">输入Bitmap</param>
3237 
3238         /// <param name="val">[0 <-明- 1 -暗-> 2]</param>
3239 
3240         /// <returns>输出Bitmap</returns>
3241 
3242         public static Bitmap SetGamma(Bitmap srcbitmap, float val)
3243 
3244         {
3245 
3246             if (srcbitmap == null)
3247 
3248             {
3249 
3250                 return null;
3251 
3252             }
3253 
3254  
3255 
3256             // 1表示无变化,就不做
3257 
3258             if (val == 1.0000f) return srcbitmap;
3259 
3260  
3261 
3262             try
3263 
3264             {
3265 
3266                 Bitmap b = new Bitmap(srcbitmap.Width, srcbitmap.Height);
3267 
3268                 Graphics g = Graphics.FromImage(b);
3269 
3270                 ImageAttributes attr = new ImageAttributes();
3271 
3272  
3273 
3274                 attr.SetGamma(val, ColorAdjustType.Bitmap);
3275 
3276                 g.DrawImage(srcbitmap, new Rectangle(0, 0, srcbitmap.Width, srcbitmap.Height), 0, 0, srcbitmap.Width, srcbitmap.Height, GraphicsUnit.Pixel, attr);
3277 
3278                 g.Dispose();
3279 
3280                 return b;
3281 
3282             }
3283 
3284             catch
3285 
3286             {
3287 
3288                 return null;
3289 
3290             }
3291 
3292         }
3293 
3294  
3295 
3296         /// <summary>         
3297 
3298         /// 重新设置图片尺寸     
3299 
3300         /// </summary> 
3301 
3302         /// <param name="srcbitmap">original Bitmap</param>         
3303 
3304         /// <param name="newW">new width</param>         
3305 
3306         /// <param name="newH">new height</param>         
3307 
3308         /// <returns>worked bitmap</returns> 
3309 
3310         public static Boolean ResizeImage(Bitmap srcimg, int newW, int newH, ref Bitmap destimage)
3311 
3312         {
3313 
3314             if (srcimg == null)
3315 
3316             {
3317 
3318                 return false;
3319 
3320             }
3321 
3322  
3323 
3324             destimage = new Bitmap(newW, newH);
3325 
3326             Graphics graph = Graphics.FromImage(destimage);
3327 
3328             Boolean bl = true;
3329 
3330             try
3331 
3332             {
3333 
3334                 graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
3335 
3336                 graph.DrawImage(srcimg, new Rectangle(0, 0, newW, newH),
3337 
3338                     new Rectangle(0, 0, srcimg.Width, srcimg.Height),
3339 
3340                     GraphicsUnit.Pixel);
3341 
3342  
3343 
3344                 graph.Dispose();
3345 
3346             }
3347 
3348             catch (Exception ex)
3349 
3350             {
3351 
3352                 Console.WriteLine("ResizeImage error" + ex.Message);
3353 
3354                 bl = false;
3355 
3356             }
3357 
3358             return bl;
3359 
3360         }
3361 
3362  
3363 
3364  
3365 
3366         /// <summary>
3367 
3368         /// 去除噪点
3369 
3370         /// </summary>
3371 
3372         /// <param name="noisypointsize">噪点的尺寸</param>
3373 
3374         /// <param name="bitmap">待处理的图片信息</param>
3375 
3376         /// <returns></returns>
3377 
3378         public static Boolean RemoveNoisypoint(Int32 noisypointsize, ref Bitmap bitmap)
3379 
3380         {
3381 
3382             if (bitmap == null || noisypointsize < 1 ||
3383 
3384                 noisypointsize * 2 >= bitmap.Width || noisypointsize * 2 >= bitmap.Height)
3385 
3386             {
3387 
3388                 return false;
3389 
3390             }
3391 
3392  
3393 
3394             // 创建过滤器
3395 
3396             BlobsFiltering blobfilter =
3397 
3398                 new BlobsFiltering();
3399 
3400             // 设置过滤条件(对象长、宽至少为70)
3401 
3402             blobfilter.CoupledSizeFiltering = true;
3403 
3404             blobfilter.MinWidth = noisypointsize;
3405 
3406             blobfilter.MinHeight = noisypointsize;
3407 
3408             blobfilter.ApplyInPlace(bitmap);
3409 
3410  
3411 
3412             return true;
3413 
3414         }
3415 
3416  
3417 
3418         /// <summary>
3419 
3420         /// 把图片里指定区域的内容复制到另一个图片里
3421 
3422         /// </summary>
3423 
3424         /// <param name="srcimg"></param>
3425 
3426         /// <param name="x"></param>
3427 
3428         /// <param name="y"></param>
3429 
3430         /// <param name="width"></param>
3431 
3432         /// <param name="height"></param>
3433 
3434         /// <param name="destimg"></param>
3435 
3436         /// <returns></returns>
3437 
3438         public static Boolean CutImage(Bitmap srcimg, Int32 x, Int32 y, Int32 width, Int32 height, ref Bitmap destimg)
3439 
3440         {
3441 
3442             if (srcimg == null || x < 0 || y < 0 || width < 1 || height < 1 ||
3443 
3444                 x + width > srcimg.Width || y + height > srcimg.Height)
3445 
3446             {
3447 
3448                 return false;
3449 
3450             }
3451 
3452  
3453 
3454             destimg = new Bitmap(width, height, PixelFormat.Format32bppArgb);
3455 
3456             Graphics graph = Graphics.FromImage(destimg);
3457 
3458             graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
3459 
3460             graph.DrawImage(srcimg, new Rectangle(0, 0, width, height),
3461 
3462                     new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
3463 
3464             graph.Dispose();
3465 
3466             return true;
3467 
3468         }
3469 
3470  
3471 
3472         #endregion
3473 
3474  
3475 
3476         #region 亮度处理
3477 
3478  
3479 
3480  
3481 
3482  
3483 
3484         /// <summary>
3485 
3486         /// 获取指定坐标处的亮度值
3487 
3488         /// </summary>
3489 
3490         /// <param name="bitmap"></param>
3491 
3492         /// <param name="x"></param>
3493 
3494         /// <param name="y"></param>
3495 
3496         /// <returns></returns>
3497 
3498         public static Boolean GetPixBrightness(Bitmap bitmap, Int32 x, Int32 y, eGrayMode mode, ref Byte brightness)
3499 
3500         {
3501 
3502             if (bitmap == null)
3503 
3504             {
3505 
3506                 return false;
3507 
3508             }
3509 
3510  
3511 
3512             if (x < 0 || x >= bitmap.Width ||
3513 
3514                 y < 0 || y >= bitmap.Height)
3515 
3516             {
3517 
3518                 return false;
3519 
3520             }
3521 
3522  
3523 
3524             Color curColor = bitmap.GetPixel(x, y);
3525 
3526             //利用公式计算灰度值(加权平均法)
3527 
3528             if (mode == eGrayMode.ArithmeticAverage)
3529 
3530             {
3531 
3532                 brightness = (Byte)(curColor.R * 0.299f + curColor.G * 0.587f + curColor.B * 0.114f);
3533 
3534             }
3535 
3536             else
3537 
3538             {
3539 
3540                 brightness = (Byte)((curColor.R + curColor.G + curColor.B) / 3.0f);
3541 
3542             }
3543 
3544             return true;
3545 
3546         }
3547 
3548  
3549 
3550         /// <summary>
3551 
3552         /// 获取指定坐标处的亮度值
3553 
3554         /// </summary>
3555 
3556         /// <param name="bitmap"></param>
3557 
3558         /// <param name="x"></param>
3559 
3560         /// <param name="y"></param>
3561 
3562         /// <returns></returns>
3563 
3564         public static Boolean GetPixBrightness(Byte[] bribytes, Int32 width,Int32 height,
3565 
3566             Int32 x, Int32 y, ref Byte brightness)
3567 
3568         {
3569 
3570             if (bribytes == null || width < 1 || height < 1 ||
3571 
3572                 x < 0 || x >= width ||
3573 
3574                 y < 0 || y >= height ||
3575 
3576                 bribytes.Length != width * height)
3577 
3578             {
3579 
3580                 return false;
3581 
3582             }
3583 
3584  
3585 
3586             brightness = bribytes[y * width + x];
3587 
3588           
3589 
3590             return true;
3591 
3592         }
3593 
3594        
3595 
3596         /// <summary>
3597 
3598         /// 获取指定坐标处的亮度值
3599 
3600         /// </summary>
3601 
3602         /// <param name="bitmap"></param>
3603 
3604         /// <param name="x"></param>
3605 
3606         /// <param name="y"></param>
3607 
3608         /// <returns></returns>
3609 
3610         public static Boolean GetPixBrightnessByRate(Byte[] bribytes, Int32 width, Int32 height,
3611 
3612             double  xRate, double yRate, ref Byte brightness)
3613 
3614         {
3615 
3616             int x = (int)(width * xRate);
3617 
3618             int y =  (int)(height * yRate);
3619 
3620  
3621 
3622             if (bribytes == null || width < 1 || height < 1 ||
3623 
3624                 x < 0 || x >= width ||
3625 
3626                 y < 0 || y >= height ||
3627 
3628                 bribytes.Length != width * height)
3629 
3630             {
3631 
3632                 return false;
3633 
3634             }
3635 
3636  
3637 
3638             brightness = bribytes[y * width + x];
3639 
3640             return true;
3641 
3642         }
3643 
3644  
3645 
3646         /// <summary>
3647 
3648         /// 获取指定坐标处的颜色
3649 
3650         /// </summary>
3651 
3652         /// <param name="bitmap"></param>
3653 
3654         /// <param name="x"></param>
3655 
3656         /// <param name="y"></param>
3657 
3658         /// <returns></returns>
3659 
3660         public static Boolean GetPixColor(Bitmap bitmap, Int32 x, Int32 y, ref Color curColor)
3661 
3662         {
3663 
3664             if (bitmap == null)
3665 
3666             {
3667 
3668                 return false;
3669 
3670             }
3671 
3672  
3673 
3674             if (x < 0 || x >= bitmap.Width ||
3675 
3676                 y < 0 || y >= bitmap.Height)
3677 
3678             {
3679 
3680                 return false;
3681 
3682             }
3683 
3684  
3685 
3686             curColor = bitmap.GetPixel(x, y);
3687 
3688             return true;
3689 
3690         }
3691 
3692        
3693 
3694         /// <summary>
3695 
3696         /// 获取指定坐标处的颜色
3697 
3698         /// </summary>
3699 
3700         /// <param name="bitmap"></param>
3701 
3702         /// <param name="x"></param>
3703 
3704         /// <param name="y"></param>
3705 
3706         /// <returns></returns>
3707 
3708         public static Boolean GetPixColorByRate(Bitmap bitmap, double xRate, double yRate, ref Color curColor)
3709 
3710         {
3711 
3712             if (bitmap == null)
3713 
3714             {
3715 
3716                 return false;
3717 
3718             }
3719 
3720  
3721 
3722             int width = bitmap.Width;
3723 
3724             int height = bitmap.Height;
3725 
3726             int X = (int)(width * xRate);
3727 
3728             int Y = (int)(height * yRate);
3729 
3730  
3731 
3732             Boolean bl = GetPixColor(bitmap, X, Y, ref curColor);
3733 
3734             return bl;
3735 
3736         }
3737 
3738  
3739 
3740         /// <summary>
3741 
3742         /// 把颜色转换为亮度值
3743 
3744         /// </summary>
3745 
3746         /// <param name="bitmap"></param>
3747 
3748         /// <param name="x"></param>
3749 
3750         /// <param name="y"></param>
3751 
3752         /// <returns></returns>
3753 
3754         public static Boolean GetBrightnessByColor(Color curColor, eGrayMode mode, ref Byte brightness)
3755 
3756         {
3757 
3758             if (curColor == null)
3759 
3760             {
3761 
3762                 return false;
3763 
3764             }
3765 
3766              
3767 
3768             //利用公式计算灰度值(加权平均法)
3769 
3770             if (mode == eGrayMode.ArithmeticAverage)
3771 
3772             {
3773 
3774                 brightness = (Byte)(curColor.R * 0.299f + curColor.G * 0.587f + curColor.B * 0.114f);
3775 
3776             }
3777 
3778             else
3779 
3780             {
3781 
3782                 brightness = (Byte)((curColor.R + curColor.G + curColor.B) / 3.0f);
3783 
3784             }
3785 
3786             return true;
3787 
3788         }
3789 
3790  
3791 
3792         #endregion
3793 
3794  
3795 
3796         #region 图片比较
3797 
3798  
3799 
3800         /// <summary>
3801 
3802         /// 根据2个图片的亮度值,比较图片的差异部分
3803 
3804         /// </summary>
3805 
3806         /// <param name="brightnessDiff"></param>
3807 
3808         /// <param name="compareret"></param>
3809 
3810         /// <returns></returns>
3811 
3812         public static Boolean CompareImageBrightness(Byte brightnessDiff,
3813 
3814             Byte[] brightness1, Byte[] brightness2,
3815 
3816             ref Boolean[] diffPixArray)
3817 
3818         {
3819 
3820  
3821 
3822             if (brightness1 == null || brightness2 == null ||
3823 
3824                 brightness1.Length < 1 || brightness2.Length < 1 ||
3825 
3826                 brightness1.Length != brightness2.Length)
3827 
3828             {
3829 
3830                 return false;
3831 
3832             }
3833 
3834  
3835 
3836             Int32 arylen = brightness1.Length;
3837 
3838             diffPixArray = new Boolean[brightness1.Length];
3839 
3840             Byte bri1 = 0;
3841 
3842             Byte bri2 = 0;
3843 
3844  
3845 
3846             for (Int32 byteidx = 0; byteidx < arylen; ++byteidx)
3847 
3848             {
3849 
3850                 bri1 = brightness1[byteidx];
3851 
3852                 bri2 = brightness2[byteidx];
3853 
3854  
3855 
3856                 //亮度差超过指定范围
3857 
3858                 if (bri1 >= bri2 + brightnessDiff ||
3859 
3860                      bri2 >= bri1 + brightnessDiff)
3861 
3862                 {
3863 
3864                     diffPixArray[byteidx] = true;
3865 
3866                 }
3867 
3868             }
3869 
3870  
3871 
3872             return true;
3873 
3874         }
3875 
3876  
3877 
3878         /// <summary>
3879 
3880         /// 把2个图片的尺寸设置为一样大
3881 
3882         /// </summary>
3883 
3884         /// <param name="image1"></param>
3885 
3886         /// <param name="image2"></param>
3887 
3888         /// <returns></returns>
3889 
3890         public static Boolean ResizeImageToSame(ref Bitmap image1, ref Bitmap image2)
3891 
3892         {
3893 
3894             if (image1 == null || image2 == null ||
3895 
3896                 image1.Width == 0 || image1.Height == 0 ||
3897 
3898                 image2.Width == 0 || image2.Height == 0)
3899 
3900             {
3901 
3902                 return false;
3903 
3904             }
3905 
3906  
3907 
3908             //如果2个图片尺寸不一样,把大的尺寸压缩小了再比较
3909 
3910             Boolean bl = false;
3911 
3912             Bitmap tmpimg = null;
3913 
3914             if (image1.Width > image2.Width && image1.Height < image2.Height)
3915 
3916             {
3917 
3918                 return false;
3919 
3920             }
3921 
3922             if (image1.Width < image2.Width && image1.Height > image2.Height)
3923 
3924             {
3925 
3926                 return false;
3927 
3928             }
3929 
3930  
3931 
3932             //image1 比较大,把image2放大到 与1一样大
3933 
3934             if (image1.Width > image2.Width && image1.Height > image2.Height)
3935 
3936             {
3937 
3938                 bl = ResizeImage(image2, image1.Width, image1.Height, ref tmpimg);
3939 
3940                 image2 = tmpimg;
3941 
3942             }
3943 
3944            
3945 
3946             //image 2比较大,把image1放大到 与2一样大
3947 
3948             if (image1.Width < image2.Width && image1.Height < image2.Height)
3949 
3950             {
3951 
3952                 bl = ResizeImage(image1, image2.Width, image2.Height, ref tmpimg);
3953 
3954                 image1 = tmpimg;
3955 
3956             }
3957 
3958  
3959 
3960             return true;
3961 
3962         }
3963 
3964         
3965 
3966         /// <summary>
3967 
3968         /// 根据2个图片的像素颜色值,比较图片的差异部分
3969 
3970         /// </summary>
3971 
3972         /// <param name="compareparam"></param>
3973 
3974         /// <param name="compareret"></param>
3975 
3976         /// <returns></returns>
3977 
3978         public static Boolean CompareImage(ImageCompareParameter compareparam,
3979 
3980             ref ImageCompareResult compareret)
3981 
3982         {
3983 
3984             Bitmap image1 = compareparam.Image1;
3985 
3986             Bitmap image2 = compareparam.Image2;
3987 
3988  
3989 
3990             Int32 briDiff = compareparam.BrightnessDiff;
3991 
3992             Color diffColor = compareparam.DifferentAreaFillColor;
3993 
3994             Color samecolor = compareparam.SameAreaFillColor;
3995 
3996             //是否需要填充相同或不同部分的像素的颜色
3997 
3998             Boolean filldiffcolor = (diffColor != Color.Transparent);
3999 
4000             Boolean fillsamecolor = (samecolor != Color.Transparent);
4001 
4002  
4003 
4004             //如果图片尺寸不一样,修改为一样大
4005 
4006             Boolean bl = ResizeImageToSame(ref image1, ref image2);
4007 
4008             if (!bl)
4009 
4010             {
4011 
4012                 return false;
4013 
4014             }
4015 
4016  
4017 
4018             Bitmap imagediff = (Bitmap)image1.Clone();
4019 
4020  
4021 
4022             //不同区域的左上下右位置
4023 
4024             Int32 areaLeft = imagediff.Width;
4025 
4026             Int32 areaTop = imagediff.Height;
4027 
4028             Int32 areaRight = -1;
4029 
4030             Int32 areaBottom = -1;
4031 
4032  
4033 
4034             int width = image1.Width;
4035 
4036             int height = image1.Height;
4037 
4038  
4039 
4040             long allpixcnt = height * width;//所有像素点数量
4041 
4042             long diffpixcnt = 0;//不同像素点数量
4043 
4044             long samepixcnt = 0;//相同像素点数量
4045 
4046  
4047 
4048             //3张图片的各像素亮度数组
4049 
4050             Int32 briaryidx = 0;
4051 
4052             Byte[] briary1 = new Byte[allpixcnt];
4053 
4054             Byte[] briary2 = new Byte[allpixcnt];
4055 
4056             Byte[] briaryret = new Byte[allpixcnt];
4057 
4058  
4059 
4060             Byte diffB = diffColor.B;
4061 
4062             Byte diffG = diffColor.G;
4063 
4064             Byte diffR = diffColor.R;
4065 
4066             Byte sameB = samecolor.B;
4067 
4068             Byte sameG = samecolor.G;
4069 
4070             Byte sameR = samecolor.R;
4071 
4072  
4073 
4074             Byte samebri = 0;
4075 
4076             Byte diffbri = 0;
4077 
4078             GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);
4079 
4080             GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);
4081 
4082  
4083 
4084             try
4085 
4086             {
4087 
4088  
4089 
4090                 BitmapData data1 = image1.LockBits(new Rectangle(0, 0, width, height),
4091 
4092                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4093 
4094  
4095 
4096                 BitmapData data2 = image2.LockBits(new Rectangle(0, 0, width, height),
4097 
4098                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4099 
4100  
4101 
4102                 BitmapData datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),
4103 
4104                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4105 
4106  
4107 
4108                 byte bri1 = 0;
4109 
4110                 byte bri2 = 0;
4111 
4112  
4113 
4114                 //每个像素是否相同.1相同,0不同
4115 
4116                 compareret.PixIsDifferent = new Boolean[width * height];
4117 
4118  
4119 
4120                 //当前像素是否不同
4121 
4122                 Boolean curpixIsdiff = false;
4123 
4124                 unsafe
4125 
4126                 {
4127 
4128                     byte* curpix1 = (byte*)data1.Scan0.ToPointer();
4129 
4130                     byte* curpix2 = (byte*)data2.Scan0.ToPointer();
4131 
4132                     byte* curpixdiff = (byte*)datadiff.Scan0.ToPointer();
4133 
4134  
4135 
4136                     for (int y = 0; y < height; y++)
4137 
4138                     {
4139 
4140                         for (int x = 0; x < width; x++)
4141 
4142                         {
4143 
4144                             //利用公式计算灰度值(加权平均法)
4145 
4146                             //按BGR的顺序存储
4147 
4148                             bri1 = (Byte)(curpix1[0] * 0.114f + curpix1[1] * 0.587f + curpix1[2] * 0.299f);
4149 
4150                             bri2 = (Byte)(curpix2[0] * 0.114f + curpix2[1] * 0.587f + curpix2[2] * 0.299f);
4151 
4152  
4153 
4154                             //以1作为基准,比较1和2之间的差距,如果超过阀值,认为当前像素有差异
4155 
4156                             //否则认为当前像素没有差异
4157 
4158                             curpixIsdiff = false;
4159 
4160                             if (bri1 >= bri2 + briDiff ||
4161 
4162                                 bri2 >= bri1 + briDiff)
4163 
4164                             {
4165 
4166                                 curpixIsdiff = true;
4167 
4168                             }
4169 
4170  
4171 
4172                             briary1[briaryidx] = bri1;
4173 
4174                             briary2[briaryidx] = bri2;
4175 
4176  
4177 
4178                             if (curpixIsdiff) //如果有差异,设置图像1里的当前像素为 不同颜色
4179 
4180                             {
4181 
4182                                 if (filldiffcolor)
4183 
4184                                 {
4185 
4186                                     curpixdiff[0] = diffB;
4187 
4188                                     curpixdiff[1] = diffG;
4189 
4190                                     curpixdiff[2] = diffR;
4191 
4192                                 }
4193 
4194                                 ++diffpixcnt;
4195 
4196  
4197 
4198                                 if (x < areaLeft) //记忆最左边的像素位置
4199 
4200                                 {
4201 
4202                                     areaLeft = x;
4203 
4204                                 }
4205 
4206                                 if (x > areaRight) //记忆最右边的像素位置
4207 
4208                                 {
4209 
4210                                     areaRight = x;
4211 
4212                                 }
4213 
4214                                 if (y < areaTop) //记忆最上边的像素位置
4215 
4216                                 {
4217 
4218                                     areaTop = y;
4219 
4220                                 }
4221 
4222                                 if (y > areaBottom) //记忆最下边的像素位置
4223 
4224                                 {
4225 
4226                                     areaBottom = y;
4227 
4228                                 }
4229 
4230  
4231 
4232                                 //记忆当前像素的比较结果的亮度
4233 
4234                                 briaryret[briaryidx] = diffbri;
4235 
4236                             }
4237 
4238                             else //没有差异,设置结果里的当前像素为 相同颜色
4239 
4240                             {
4241 
4242                                 if (fillsamecolor)
4243 
4244                                 {
4245 
4246                                     curpixdiff[0] = sameB;
4247 
4248                                     curpixdiff[1] = sameG;
4249 
4250                                     curpixdiff[2] = sameR;
4251 
4252                                 }
4253 
4254                                 ++samepixcnt;
4255 
4256  
4257 
4258                                 //记忆当前像素的比较结果的亮度
4259 
4260                                 briaryret[briaryidx] = samebri;
4261 
4262                             }
4263 
4264  
4265 
4266                             // 比较结果的亮度数组下标
4267 
4268                             ++briaryidx;
4269 
4270  
4271 
4272                             //像素是否不同的标志
4273 
4274                             compareret.PixIsDifferent[y * width + x] = curpixIsdiff;
4275 
4276  
4277 
4278                             curpix1 += 3;
4279 
4280                             curpix2 += 3;
4281 
4282                             curpixdiff += 3;
4283 
4284                         }
4285 
4286                         curpix1 += data1.Stride - width * 3;
4287 
4288                         curpix2 += data1.Stride - width * 3;
4289 
4290                         curpixdiff += datadiff.Stride - width * 3;
4291 
4292                     }
4293 
4294                 }
4295 
4296  
4297 
4298                 image1.UnlockBits(data1);
4299 
4300                 image2.UnlockBits(data2);
4301 
4302                 imagediff.UnlockBits(datadiff);
4303 
4304  
4305 
4306                 compareret.RateDifferent = diffpixcnt / (double)allpixcnt;
4307 
4308                 compareret.RateSame = samepixcnt / (double)allpixcnt;
4309 
4310  
4311 
4312                 compareret.CompareResultImage = imagediff;
4313 
4314                 compareret.BrightnessDiff = briDiff;
4315 
4316  
4317 
4318                 compareret.BrightnessBytesImage1 = briary1;
4319 
4320                 compareret.BrightnessBytesImage2 = briary2;
4321 
4322                 compareret.BrightnessBytesResult = briaryret;
4323 
4324  
4325 
4326                 //保存区域范围
4327 
4328                 //compareret.DiffAreaTop = areaTop;
4329 
4330                 //compareret.DiffAreaLeft = areaLeft;
4331 
4332                 //compareret.DiffAreaRight = areaRight;
4333 
4334                 //compareret.DiffAreaBottom = areaBottom;
4335 
4336                 //compareret.CalculateAreaRate();
4337 
4338  
4339 
4340                 bl = true;
4341 
4342             }
4343 
4344             catch (Exception ex)
4345 
4346             {
4347 
4348                 Console.WriteLine("CompareImage error:" + ex.Message);
4349 
4350                 bl = false;
4351 
4352             }
4353 
4354  
4355 
4356             return bl;
4357 
4358         }
4359 
4360  
4361 
4362  
4363 
4364         /// <summary>
4365 
4366         /// 2张图片亮度值相减,得到新图片以及亮度值
4367 
4368         /// </summary>
4369 
4370         /// <param name="image1"></param>
4371 
4372         /// <param name="image2"></param>
4373 
4374         /// <param name="retimage"></param>
4375 
4376         /// <param name="brightnessary"></param>
4377 
4378         /// <returns></returns>
4379 
4380         public static Boolean SubtractImageBrightness(Bitmap image1, Bitmap image2,
4381 
4382             ref Bitmap imagediff, ref Byte[] brightnessary)
4383 
4384         {
4385 
4386             if (image1 == null || image2 == null)
4387 
4388             {
4389 
4390                 return false;
4391 
4392             }
4393 
4394  
4395 
4396             Boolean bl = ResizeImageToSame(ref image1, ref image2);
4397 
4398             if (!bl)
4399 
4400             {
4401 
4402                 return false;
4403 
4404             }
4405 
4406            
4407 
4408             int width = image1.Width;
4409 
4410             int height = image1.Height;
4411 
4412  
4413 
4414             long allpixcnt = height * width;//所有像素点数量             
4415 
4416  
4417 
4418             brightnessary = new Byte[allpixcnt];
4419 
4420             imagediff = new Bitmap(image1);
4421 
4422             Int32 pixidx = 0;//当前像素下标
4423 
4424             byte bri1 = 0;
4425 
4426             byte bri2 = 0;
4427 
4428             BitmapData data1 = null;
4429 
4430             BitmapData data2 = null;
4431 
4432             BitmapData datadiff = null;
4433 
4434             //每行末尾还有这么多的冗余字节
4435 
4436             Int32 rowredundancy = 0;
4437 
4438  
4439 
4440             try
4441 
4442             {
4443 
4444                 data1 = image1.LockBits(new Rectangle(0, 0, width, height),
4445 
4446                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4447 
4448  
4449 
4450                 data2 = image2.LockBits(new Rectangle(0, 0, width, height),
4451 
4452                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4453 
4454  
4455 
4456                 datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),
4457 
4458                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4459 
4460  
4461 
4462                 rowredundancy = datadiff.Stride - width * 3;//每行末尾还有这么多的冗余字节
4463 
4464                 Byte bridiff = 0;
4465 
4466                 unsafe
4467 
4468                 {
4469 
4470                     byte* curpix1 = (byte*)data1.Scan0.ToPointer();
4471 
4472                     byte* curpix2 = (byte*)data2.Scan0.ToPointer();
4473 
4474                     byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
4475 
4476  
4477 
4478                     for (int y = 0; y < height; y++)
4479 
4480                     {
4481 
4482                         for (int x = 0; x < width; x++)
4483 
4484                         {
4485 
4486                             bri1 = (byte)((float)(curpix1[0] + curpix1[1] + curpix1[2]) / 3.0f);
4487 
4488                             bri2 = (byte)((float)(curpix2[0] + curpix2[1] + curpix2[2]) / 3.0f);
4489 
4490  
4491 
4492                             bridiff = (bri1 > bri2) ? (Byte)(bri1 - bri2) : (Byte)(bri2 - bri1); //计算当前像素点的亮度值
4493 
4494                             brightnessary[pixidx] = bridiff;//保存亮度值
4495 
4496                             ++pixidx;
4497 
4498  
4499 
4500                             cmpretpix[0] = bridiff;//把亮度值设置到结果图像里
4501 
4502                             cmpretpix[1] = bridiff;
4503 
4504                             cmpretpix[2] = bridiff;
4505 
4506                            
4507 
4508                             curpix1 += 3;
4509 
4510                             curpix2 += 3;
4511 
4512                             cmpretpix += 3;
4513 
4514                         }
4515 
4516                         curpix1 += rowredundancy;
4517 
4518                         curpix2 += rowredundancy;
4519 
4520                         cmpretpix += rowredundancy;
4521 
4522                     }
4523 
4524                 }
4525 
4526  
4527 
4528                 image1.UnlockBits(data1);
4529 
4530                 image2.UnlockBits(data2);
4531 
4532                 imagediff.UnlockBits(datadiff);
4533 
4534                 bl = true;
4535 
4536             }
4537 
4538             catch (Exception ex)
4539 
4540             {
4541 
4542                 Console.WriteLine("CompareImage error:" + ex.Message);
4543 
4544                 bl = false;
4545 
4546             }
4547 
4548  
4549 
4550             return bl;
4551 
4552         }
4553 
4554  
4555 
4556         /// <summary>
4557 
4558         /// 根据2个图片的亮度值,比较图片的差异部分,并对比较结果的图片执行去噪点处理
4559 
4560         /// </summary>
4561 
4562         /// <param name="image1"></param>
4563 
4564         /// <param name="image2"></param>
4565 
4566         /// <param name="bridiff">亮度容差</param>
4567 
4568         /// <param name="noisypointsize">噪点边长</param>
4569 
4570         /// <param name="imagediff">比较结果的图片</param>
4571 
4572         /// <param name="diffary">每个像素是否相同</param>
4573 
4574         /// <returns></returns>
4575 
4576         public static Boolean CompareImageByBrightness(Bitmap image1, Bitmap image2,
4577 
4578             Int32 briDiff, Int32 noisypointsize,
4579 
4580             ref Bitmap imagediff, ref Boolean[] diffary)
4581 
4582         {
4583 
4584             if (image1 == null || image2 == null)
4585 
4586             {
4587 
4588                 return false;
4589 
4590             }
4591 
4592  
4593 
4594             Boolean bl = ResizeImageToSame(ref image1, ref image2);
4595 
4596             if (!bl)
4597 
4598             {
4599 
4600                 return false;
4601 
4602             }
4603 
4604  
4605 
4606             if (briDiff < 1 || briDiff > 255)
4607 
4608             {
4609 
4610                 return false;
4611 
4612             }
4613 
4614  
4615 
4616             if (noisypointsize < 1 || noisypointsize * 2 > image1.Height)
4617 
4618             {
4619 
4620                 return false;
4621 
4622             }
4623 
4624            
4625 
4626             int width = image1.Width;
4627 
4628             int height = image1.Height;
4629 
4630  
4631 
4632             long allpixcnt = height * width;//所有像素点数量
4633 
4634             
4635 
4636             imagediff = new Bitmap(image1);
4637 
4638            
4639 
4640             //每个像素是否相同.1相同,0不同
4641 
4642             diffary = new Boolean[width * height];
4643 
4644  
4645 
4646             Int32 pixidx = 0;//当前像素下标
4647 
4648             byte bri1 = 0;
4649 
4650             byte bri2 = 0;
4651 
4652             BitmapData data1 = null;
4653 
4654             BitmapData data2 = null;
4655 
4656             BitmapData datadiff = null;
4657 
4658             //每行末尾还有这么多的冗余字节
4659 
4660             Int32 rowredundancy = 0;
4661 
4662  
4663 
4664             try
4665 
4666             {
4667 
4668                 data1 = image1.LockBits(new Rectangle(0, 0, width, height),
4669 
4670                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4671 
4672  
4673 
4674                 data2 = image2.LockBits(new Rectangle(0, 0, width, height),
4675 
4676                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4677 
4678  
4679 
4680                 datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),
4681 
4682                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4683 
4684  
4685 
4686                 rowredundancy = datadiff.Stride - width * 3;//每行末尾还有这么多的冗余字节
4687 
4688  
4689 
4690                 unsafe
4691 
4692                 {
4693 
4694                     byte* curpix1 = (byte*)data1.Scan0.ToPointer();
4695 
4696                     byte* curpix2 = (byte*)data2.Scan0.ToPointer();
4697 
4698                     byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
4699 
4700  
4701 
4702                     for (int y = 0; y < height; y++)
4703 
4704                     {
4705 
4706                         for (int x = 0; x < width; x++)
4707 
4708                         {
4709 
4710                             bri1 = (byte)((float)(curpix1[0] + curpix1[1] + curpix1[2]) / 3.0f);
4711 
4712                             bri2 = (byte)((float)(curpix2[0] + curpix2[1] + curpix2[2]) / 3.0f);
4713 
4714  
4715 
4716                             //比较2个像素亮度值之差,如果有差异,设置图像1里的当前像素为 不同颜色
4717 
4718                             if (bri1 >= bri2 + briDiff ||
4719 
4720                               bri2 >= bri1 + briDiff)
4721 
4722                             {
4723 
4724                                 diffary[pixidx] = true;
4725 
4726                                 cmpretpix[0] = Const_WhiteBrightness;
4727 
4728                                 cmpretpix[1] = Const_WhiteBrightness;
4729 
4730                                 cmpretpix[2] = Const_WhiteBrightness;
4731 
4732                             }
4733 
4734                             else
4735 
4736                             {
4737 
4738                                 diffary[pixidx] = false;
4739 
4740                                 cmpretpix[0] = Const_BlackBrightness;
4741 
4742                                 cmpretpix[1] = Const_BlackBrightness;
4743 
4744                                 cmpretpix[2] = Const_BlackBrightness;
4745 
4746                             }
4747 
4748  
4749 
4750                             ++pixidx;
4751 
4752                             curpix1 += 3;
4753 
4754                             curpix2 += 3;
4755 
4756                             cmpretpix += 3;
4757 
4758                         }
4759 
4760                         curpix1 += rowredundancy;
4761 
4762                         curpix2 += rowredundancy;
4763 
4764                         cmpretpix += rowredundancy;
4765 
4766                     }
4767 
4768                 }
4769 
4770  
4771 
4772                 image1.UnlockBits(data1);
4773 
4774                 image2.UnlockBits(data2);
4775 
4776                 imagediff.UnlockBits(datadiff);
4777 
4778                 bl = true;
4779 
4780             }
4781 
4782             catch (Exception ex)
4783 
4784             {
4785 
4786                 Console.WriteLine("CompareImage error:" + ex.Message);
4787 
4788                 bl = false;
4789 
4790             }
4791 
4792  
4793 
4794             //现在对图像执行去噪点处理
4795 
4796             RemoveNoisypoint(noisypointsize, ref imagediff);
4797 
4798  
4799 
4800             //获取去除噪点后各像素亮度
4801 
4802             Byte pixbri = 0;//当前像素亮度
4803 
4804             pixidx = 0;
4805 
4806             try
4807 
4808             {
4809 
4810                 datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),
4811 
4812                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
4813 
4814                 unsafe
4815 
4816                 {
4817 
4818                     byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
4819 
4820  
4821 
4822                     for (int y = 0; y < height; y++)
4823 
4824                     {
4825 
4826                         for (int x = 0; x < width; x++)
4827 
4828                         {
4829 
4830                             pixbri = (byte)((float)(cmpretpix[0] + cmpretpix[1] + cmpretpix[2]) / 3.0f);
4831 
4832  
4833 
4834                             //去除噪点后,已经变得非黑即白.如果是黑色,表示相同,白色,表示不同
4835 
4836                             diffary[pixidx] = (pixbri > briDiff);
4837 
4838                             ++pixidx;
4839 
4840                             cmpretpix += 3;
4841 
4842                         }
4843 
4844                         cmpretpix += rowredundancy;
4845 
4846                     }
4847 
4848                 }
4849 
4850  
4851 
4852                 imagediff.UnlockBits(datadiff);
4853 
4854                 bl = true;
4855 
4856             }
4857 
4858             catch (Exception ex)
4859 
4860             {
4861 
4862                 Console.WriteLine("CompareImage error:" + ex.Message);
4863 
4864                 bl = false;
4865 
4866             }
4867 
4868             return bl;
4869 
4870         }
4871 
4872  
4873 
4874         /// 根据2个图片的亮度值,比较图片的差异部分
4875 
4876         /// </summary>
4877 
4878         /// <param name="compareparam"></param>
4879 
4880         /// <param name="compareret"></param>
4881 
4882         /// <returns></returns>
4883 
4884         public static Boolean CompareImageByBrightness(ImageCompareParameter compareparam,
4885 
4886             ref ImageCompareResult compareret)
4887 
4888         {
4889 
4890             Bitmap image1 = compareparam.Image1;
4891 
4892             Bitmap image2 = compareparam.Image2;
4893 
4894  
4895 
4896             Byte[] imagebri1 = compareparam.BrightnessBytesImage1;
4897 
4898             Byte[] imagebri2 = compareparam.BrightnessBytesImage2;
4899 
4900  
4901 
4902             Int32 briDiff = compareparam.BrightnessDiff;
4903 
4904             Color diffColor = compareparam.DifferentAreaFillColor;
4905 
4906             Color samecolor = compareparam.SameAreaFillColor;
4907 
4908             //是否需要填充相同或不同部分的像素的颜色
4909 
4910             Boolean filldiffcolor = (diffColor != Color.Transparent);
4911 
4912             Boolean fillsamecolor = (samecolor != Color.Transparent);
4913 
4914  
4915 
4916             Boolean bl = false;
4917 
4918  
4919 
4920             Bitmap imagediff = new Bitmap(image1);
4921 
4922  
4923 
4924             //不同区域的左上下右位置
4925 
4926             Int32 areaLeft = imagediff.Width;
4927 
4928             Int32 areaTop = imagediff.Height;
4929 
4930             Int32 areaRight = -1;
4931 
4932             Int32 areaBottom = -1;
4933 
4934  
4935 
4936             int width = image1.Width;
4937 
4938             int height = image1.Height;
4939 
4940  
4941 
4942             long allpixcnt = height * width;//所有像素点数量
4943 
4944             long diffpixcnt = 0;//不同像素点数量
4945 
4946             long samepixcnt = 0;//相同像素点数量
4947 
4948            
4949 
4950             if (imagebri1 == null || imagebri2 == null ||
4951 
4952                 imagebri2.Length != imagebri2.Length ||
4953 
4954                 imagebri2.Length != allpixcnt)
4955 
4956             {
4957 
4958                 return false;
4959 
4960             }
4961 
4962  
4963 
4964             //3张图片的各像素亮度数组
4965 
4966             Int32 briaryidx = 0;
4967 
4968             Byte[] briaryret = new Byte[allpixcnt];
4969 
4970  
4971 
4972             Byte diffB = diffColor.B;
4973 
4974             Byte diffG = diffColor.G;
4975 
4976             Byte diffR = diffColor.R;
4977 
4978             Byte sameB = samecolor.B;
4979 
4980             Byte sameG = samecolor.G;
4981 
4982             Byte sameR = samecolor.R;
4983 
4984  
4985 
4986             Byte samebri = 0;
4987 
4988             Byte diffbri = 0;
4989 
4990             GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);
4991 
4992             GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);
4993 
4994  
4995 
4996             Int32 currowfirstx = 0;//当前行的首个像素的下标
4997 
4998             try
4999 
5000             {
5001 
5002  
5003 
5004                 BitmapData data1 = image1.LockBits(new Rectangle(0, 0, width, height),
5005 
5006                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
5007 
5008  
5009 
5010                 BitmapData data2 = image2.LockBits(new Rectangle(0, 0, width, height),
5011 
5012                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
5013 
5014  
5015 
5016                 BitmapData datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),
5017 
5018                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
5019 
5020  
5021 
5022                 byte bri1 = 0;
5023 
5024                 byte bri2 = 0;
5025 
5026  
5027 
5028                 //每个像素是否相同.1相同,0不同
5029 
5030                 compareret.PixIsDifferent = new Boolean[width * height];
5031 
5032  
5033 
5034                 //当前像素是否不同
5035 
5036                 Boolean curpixIsdiff = false;
5037 
5038                 unsafe
5039 
5040                 {
5041 
5042                     byte* curpix1 = (byte*)data1.Scan0.ToPointer();
5043 
5044                     byte* curpix2 = (byte*)data2.Scan0.ToPointer();
5045 
5046                     byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
5047 
5048  
5049 
5050                     for (int y = 0; y < height; y++)
5051 
5052                     {
5053 
5054                         currowfirstx = y * width;
5055 
5056                         for (int x = 0; x < width; x++)
5057 
5058                         {
5059 
5060                             bri1 = imagebri1[currowfirstx + x];
5061 
5062                             bri2 = imagebri2[currowfirstx + x];
5063 
5064  
5065 
5066                             //以1作为基准,比较1和2之间的差距,如果超过阀值,认为当前像素有差异
5067 
5068                             //否则认为当前像素没有差异
5069 
5070                             curpixIsdiff = false;
5071 
5072                             if (bri1 >= bri2 + briDiff ||
5073 
5074                                 bri2 >= bri1 + briDiff)
5075 
5076                             {
5077 
5078                                 curpixIsdiff = true;
5079 
5080                             }
5081 
5082  
5083 
5084                             if (curpixIsdiff) //如果有差异,设置图像1里的当前像素为 不同颜色
5085 
5086                             {
5087 
5088                                 if (filldiffcolor)
5089 
5090                                 {
5091 
5092                                     cmpretpix[0] = diffB;
5093 
5094                                     cmpretpix[1] = diffG;
5095 
5096                                     cmpretpix[2] = diffR;
5097 
5098                                 }
5099 
5100                                 ++diffpixcnt;
5101 
5102  
5103 
5104                                 if (x < areaLeft) //记忆最左边的像素位置
5105 
5106                                 {
5107 
5108                                     areaLeft = x;
5109 
5110                                 }
5111 
5112                                 if (x > areaRight) //记忆最右边的像素位置
5113 
5114                                 {
5115 
5116                                     areaRight = x;
5117 
5118                                 }
5119 
5120                                 if (y < areaTop) //记忆最上边的像素位置
5121 
5122                                 {
5123 
5124                                     areaTop = y;
5125 
5126                                 }
5127 
5128                                 if (y > areaBottom) //记忆最下边的像素位置
5129 
5130                                 {
5131 
5132                                     areaBottom = y;
5133 
5134                                 }
5135 
5136  
5137 
5138                                 //记忆当前像素的比较结果的亮度
5139 
5140                                 briaryret[briaryidx] = diffbri;
5141 
5142                             }
5143 
5144                             else //没有差异,设置结果里的当前像素为 相同颜色
5145 
5146                             {
5147 
5148                                 if (fillsamecolor)
5149 
5150                                 {
5151 
5152                                     cmpretpix[0] = sameB;
5153 
5154                                     cmpretpix[1] = sameG;
5155 
5156                                     cmpretpix[2] = sameR;
5157 
5158                                 }
5159 
5160                                 ++samepixcnt;
5161 
5162  
5163 
5164                                 //记忆当前像素的比较结果的亮度
5165 
5166                                 briaryret[briaryidx] = samebri;
5167 
5168                             }
5169 
5170  
5171 
5172                             // 比较结果的亮度数组下标
5173 
5174                             ++briaryidx;
5175 
5176  
5177 
5178                             //像素是否不同的标志
5179 
5180                             compareret.PixIsDifferent[currowfirstx + x] = curpixIsdiff;
5181 
5182  
5183 
5184                             curpix1 += 3;
5185 
5186                             curpix2 += 3;
5187 
5188                             cmpretpix += 3;
5189 
5190                         }
5191 
5192                         curpix1 += data1.Stride - width * 3;
5193 
5194                         curpix2 += data1.Stride - width * 3;
5195 
5196                         cmpretpix += datadiff.Stride - width * 3;
5197 
5198                     }
5199 
5200                 }
5201 
5202  
5203 
5204                 image1.UnlockBits(data1);
5205 
5206                 image2.UnlockBits(data2);
5207 
5208                 imagediff.UnlockBits(datadiff);
5209 
5210  
5211 
5212                 compareret.RateDifferent = diffpixcnt / (double)allpixcnt;
5213 
5214                 compareret.RateSame = samepixcnt / (double)allpixcnt;
5215 
5216  
5217 
5218                 compareret.CompareResultImage = imagediff;
5219 
5220                 compareret.BrightnessDiff = briDiff;
5221 
5222                 compareret.BrightnessBytesResult = briaryret;
5223 
5224  
5225 
5226                 bl = true;
5227 
5228             }
5229 
5230             catch (Exception ex)
5231 
5232             {
5233 
5234                 Console.WriteLine("CompareImage error:" + ex.Message);
5235 
5236                 bl = false;
5237 
5238             }
5239 
5240  
5241 
5242             return bl;
5243 
5244         }
5245 
5246  
5247 
5248         /// <summary>
5249 
5250         /// 获取一个区域的实际坐标
5251 
5252         /// </summary>
5253 
5254         /// <param name="area"></param>
5255 
5256         /// <param name="width"></param>
5257 
5258         /// <param name="height"></param>
5259 
5260         /// <param name="x1"></param>
5261 
5262         /// <param name="y1"></param>
5263 
5264         /// <param name="x2"></param>
5265 
5266         /// <param name="y2"></param>
5267 
5268         public static void GetAreaPositionInImage(ImageAreaInfo area,
5269 
5270             Int32 width, Int32 height,
5271 
5272             ref Int32 x1, ref Int32 y1, ref Int32 x2, ref Int32 y2)
5273 
5274         {
5275 
5276             if (area.PositionType == ePositionType.ByPix)
5277 
5278             {
5279 
5280                 x1 = (Int32)area.X1;
5281 
5282                 y1 = (Int32)area.Y1;
5283 
5284                 x2 = (Int32)area.X2;
5285 
5286                 y2 = (Int32)area.Y2;
5287 
5288             }
5289 
5290             else
5291 
5292             {
5293 
5294                 x1 = (Int32)(area.X1 * (double)width);
5295 
5296                 y1 = (Int32)(area.Y1 * (double)height);
5297 
5298                 x2 = (Int32)(area.X2 * (double)width);
5299 
5300                 y2 = (Int32)(area.Y2 * (double)height);
5301 
5302             }
5303 
5304         }
5305 
5306  
5307 
5308         /// <summary>
5309 
5310         /// 检查指定区域的图像是否与方案里的指定值一样(都是相同或者不同)
5311 
5312         /// </summary>
5313 
5314         /// <param name="briDiffary">每个元素对应2张图片的每个像素亮度相同还是不同.true不同,false相同</param>
5315 
5316         /// <param name="area"></param>
5317 
5318         /// <returns></returns>
5319 
5320         public static Boolean ValidateImageArea(Boolean[] briDiffary, ImageAreaInfo area, Int32 width, Int32 height)
5321 
5322         {
5323 
5324             if (briDiffary == null || briDiffary.Length < 4 || area == null ||
5325 
5326                 width < 1 || height < 1 || width * height != briDiffary.Length)
5327 
5328             {
5329 
5330                 return false;
5331 
5332             }
5333 
5334  
5335 
5336             Int32 x1 = 0;
5337 
5338             Int32 x2 = 0;
5339 
5340             Int32 y1 = 0;
5341 
5342             Int32 y2 = 0;
5343 
5344  
5345 
5346             //获取该区域在图像里的实际坐标范围
5347 
5348             GetAreaPositionInImage(area, width, height,
5349 
5350                 ref x1, ref y1, ref x2, ref y2);
5351 
5352  
5353 
5354             //获取该区域里的像素匹配类型
5355 
5356             eAreaDifferentType difftype = eAreaDifferentType.Partial;
5357 
5358             Boolean bl = GetImageAreaDifferentType(briDiffary, width, height,
5359 
5360                 x1, y1, x2, y2, ref difftype);
5361 
5362             if (!bl)
5363 
5364             {
5365 
5366                 return false;
5367 
5368             }
5369 
5370  
5371 
5372             //如果是期待所有像素都是相同,要求必须每个像素都相同.任何一个不同,就认为失败
5373 
5374             if (area.ExpectDispMode == eDrawType.ExpectHide &&
5375 
5376                 difftype != eAreaDifferentType.AllSame)
5377 
5378             {
5379 
5380                 return false;
5381 
5382             }
5383 
5384  
5385 
5386             //如果是期待像素不同,只要有1个像素不同就可以.所有像素都相同,认为失败
5387 
5388             if (area.ExpectDispMode == eDrawType.ExpectShow &&
5389 
5390                 difftype == eAreaDifferentType.AllSame)
5391 
5392             {
5393 
5394                 return false;
5395 
5396             }
5397 
5398             return true;
5399 
5400         }
5401 
5402  
5403 
5404         /// <summary>
5405 
5406         /// 检查指定区域的图像是否与方案里的指定值一样(都是相同或者不同)
5407 
5408         /// </summary>
5409 
5410         /// <param name="pixDiffary"></param>
5411 
5412         /// <param name="area"></param>
5413 
5414         /// <returns></returns>
5415 
5416         public static Boolean ValidateImageArea(Byte[] briDiffary, ImageAreaInfo area, Int32 width, Int32 height)
5417 
5418         {
5419 
5420  
5421 
5422             Boolean[] blary = new Boolean[briDiffary.Length];
5423 
5424             for (Int32 idx = 0; idx < briDiffary.Length; ++idx)
5425 
5426             {
5427 
5428                 blary[idx] = (briDiffary[idx] > 0);
5429 
5430             }
5431 
5432  
5433 
5434             Boolean bl = ValidateImageArea(blary, area, width, height);
5435 
5436             return bl;
5437 
5438         }
5439 
5440        
5441 
5442         /// <summary>
5443 
5444         /// 检查图片的比较结果里,某个区域是否与期待的一致
5445 
5446         /// </summary>
5447 
5448         /// <param name="compareret"></param>
5449 
5450         /// <param name="area"></param>
5451 
5452         /// <returns>true-与期待一致;false-不一致</returns>
5453 
5454         public static Boolean ValidateImageArea(ImageCompareResult compareret, ImageAreaInfo area)
5455 
5456         {
5457 
5458             Boolean[] pixDiffary = compareret.PixIsDifferent;
5459 
5460  
5461 
5462             Bitmap tmp = new Bitmap(compareret.CompareResultImage);
5463 
5464             Int32 width = tmp.Width;
5465 
5466             Int32 height = tmp.Height;
5467 
5468             Boolean bl = ValidateImageArea(compareret.PixIsDifferent, area, width, height);
5469 
5470  
5471 
5472             return bl;
5473 
5474         }
5475 
5476       
5477 
5478         /// <summary>
5479 
5480         /// 获取1个 比较结果里,指定的区域范围,是全都相同,还是不同
5481 
5482         /// 只有所有像素都是相同,才认为是整个区域相同
5483 
5484         /// 如果有1个像素不同,则认为整个区域不同
5485 
5486         /// </summary>
5487 
5488         /// <param name="pixDiffary"></param>
5489 
5490         /// <param name="width"></param>
5491 
5492         /// <param name="height"></param>
5493 
5494         /// <param name="startX"></param>
5495 
5496         /// <param name="startY"></param>
5497 
5498         /// <param name="endX"></param>
5499 
5500         /// <param name="endY"></param>
5501 
5502         /// <returns> </returns>
5503 
5504         public static Boolean GetImageAreaDifferentType(Boolean[] pixDiffary, Int32 width, Int32 height,
5505 
5506             Int32 x1, Int32 y1, Int32 x2, Int32 y2, ref eAreaDifferentType difftype)
5507 
5508         {
5509 
5510             Int32 areawidth = x2 - x1;
5511 
5512             Int32 areaheight = y2 - y1;
5513 
5514  
5515 
5516             if (pixDiffary == null || width < 1 || height < 1 ||
5517 
5518                 areawidth < 1 || areaheight < 1 ||
5519 
5520                 width < areawidth || height < areaheight ||
5521 
5522                 pixDiffary.Length < width * height)
5523 
5524             {
5525 
5526                 return false;
5527 
5528             }
5529 
5530  
5531 
5532             Boolean allissame = false; //假设所有像素相同
5533 
5534             Boolean allisdiff = false; //假设所有像素不同
5535 
5536  
5537 
5538             Int32 currowFirstPix = 0;
5539 
5540             for (Int32 y = y1; y <= y2; ++y)
5541 
5542             {
5543 
5544                 currowFirstPix = y * width;
5545 
5546                 for (Int32 x = x1; x <= x2; ++x)
5547 
5548                 {
5549 
5550                     if (pixDiffary[currowFirstPix + x]) //当前像素点不同
5551 
5552                     {
5553 
5554                         allisdiff = true;
5555 
5556                     }
5557 
5558                     else//当前像素相同
5559 
5560                     {
5561 
5562                         allissame = true;
5563 
5564                     }
5565 
5566  
5567 
5568                     //如果已经有部分相同部分不同,退出
5569 
5570                     if (allisdiff && allissame)
5571 
5572                     {
5573 
5574                         difftype = eAreaDifferentType.Partial;
5575 
5576                         return true;
5577 
5578                     }
5579 
5580                 }
5581 
5582             }
5583 
5584  
5585 
5586             //现在,所有像素都相同,或都不同
5587 
5588             if (allisdiff)
5589 
5590             {
5591 
5592                 difftype = eAreaDifferentType.AllDifferent;
5593 
5594             }
5595 
5596             else
5597 
5598             {
5599 
5600                 difftype = eAreaDifferentType.AllSame;
5601 
5602             }
5603 
5604             return true;
5605 
5606         }
5607 
5608  
5609 
5610         /// <summary>
5611 
5612         /// 根据亮度容差,把图片转换为非黑即白的图片
5613 
5614         /// </summary>
5615 
5616         /// <param name="briimg"></param>
5617 
5618         /// <param name="brigate"></param>
5619 
5620         /// <returns></returns>
5621 
5622         public static Boolean GetBlackWhiteImage(Bitmap briimg, Byte[] briDiffary, Int32 brigate, ref Bitmap blackwhiteimage)
5623 
5624         {
5625 
5626             if (briimg == null)
5627 
5628             {
5629 
5630                 return false;
5631 
5632             }
5633 
5634  
5635 
5636             int width = briimg.Width;
5637 
5638             int height = briimg.Height;
5639 
5640  
5641 
5642             long allpixcnt = height * width;//所有像素点数量            
5643 
5644  
5645 
5646             if (briDiffary == null || briDiffary.Length != allpixcnt)
5647 
5648             {
5649 
5650                 return false;
5651 
5652             }
5653 
5654  
5655 
5656             blackwhiteimage = new Bitmap(briimg);
5657 
5658             Int32 pixidx = 0;//当前像素下标
5659 
5660             BitmapData datasrc = null;
5661 
5662             BitmapData dataret = null;
5663 
5664  
5665 
5666             //每行末尾还有这么多的冗余字节
5667 
5668             Int32 rowredundancy = 0;
5669 
5670  
5671 
5672             Byte curpixBri = 0;//当前的亮度
5673 
5674             try
5675 
5676             {
5677 
5678                 datasrc = briimg.LockBits(new Rectangle(0, 0, width, height),
5679 
5680                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
5681 
5682  
5683 
5684                 dataret = blackwhiteimage.LockBits(new Rectangle(0, 0, width, height),
5685 
5686                     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
5687 
5688  
5689 
5690                 rowredundancy = datasrc.Stride - width * 3;//每行末尾还有这么多的冗余字节
5691 
5692                 unsafe
5693 
5694                 {
5695 
5696                     byte* pixret = (byte*)dataret.Scan0.ToPointer();
5697 
5698  
5699 
5700                     for (int y = 0; y < height; y++)
5701 
5702                     {
5703 
5704                         for (int x = 0; x < width; x++)
5705 
5706                         {
5707 
5708                             //亮度差值大于门限的,认为是不同部分,用白色填充
5709 
5710                             curpixBri = (briDiffary[pixidx] > brigate) ? Const_BrightnessWhite : Const_BrightnessBlack;
5711 
5712                             pixret[0] = curpixBri;//把亮度值设置到结果图像里
5713 
5714                             pixret[1] = curpixBri;
5715 
5716                             pixret[2] = curpixBri;
5717 
5718                             ++pixidx;
5719 
5720                             pixret += 3;
5721 
5722                         }
5723 
5724                         pixret += rowredundancy;
5725 
5726                     }
5727 
5728                 }
5729 
5730  
5731 
5732                 briimg.UnlockBits(datasrc);
5733 
5734                 blackwhiteimage.UnlockBits(dataret);
5735 
5736             }
5737 
5738             catch (Exception ex)
5739 
5740             {
5741 
5742                 Console.WriteLine("GetBlackWhiteImage error:" + ex.Message);
5743 
5744                 return false;
5745 
5746             }
5747 
5748  
5749 
5750             return true;
5751 
5752         }
5753 
5754         #endregion
5755 
5756        
5757 
5758         #region 内部实现
5759 
5760  
5761 
5762  
5763 
5764         /// <summary>
5765 
5766         /// 比较2个数值之间的差是否大于指定值
5767 
5768         /// </summary>
5769 
5770         /// <param name="val1"></param>
5771 
5772         /// <param name="val2"></param>
5773 
5774         /// <param name="diff"></param>
5775 
5776         /// <returns>超过指定值返回true;否则返回false</returns>
5777 
5778         private static Boolean CheckDiffOver(Int32 val1, Int32 val2, Int32 diff)
5779 
5780         {
5781 
5782             if (diff < 1)
5783 
5784             {
5785 
5786                 return false;
5787 
5788             }
5789 
5790             if (val1 > val2 && val1 > val2 + diff)
5791 
5792             {
5793 
5794                 return true;
5795 
5796             }
5797 
5798             if (val2 > val1 && val2 > val1 + diff)
5799 
5800             {
5801 
5802                 return true;
5803 
5804             }
5805 
5806             return false;
5807 
5808         }
5809 
5810         #endregion
5811 
5812     }
5813 
5814 }

 

posted @ 2017-01-04 11:31  安度  阅读(11401)  评论(0编辑  收藏  举报