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