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

【转】C#使用ESC指令控制POS打印机打印小票的更多相关文章

  1. C#使用ESC指令控制POS打印机打印小票

    1.前言 C#打印小票可以与普通打印机一样,调用PrintDocument实现.也可以发送标注你的ESC指令实现.由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的po ...

  2. android 控制POS机图文打印(二)

    上一篇文章结束了ESC/POS的指令集,没看过的可以去看一下,可以当作工具文档来使用的 android 控制POS机图文打印(一) 这一篇正式介绍如何使用POS机来打印图文信息. 首先介绍一下,ESC ...

  3. Java 实现 POS 打印机无驱打印

    来源:https://www.ibm.com/developerworks/cn/java/j-lo-pos/index.html 行业需求 我们是一家专业做酒店餐饮软件的公司,餐饮软件一个重要的功能 ...

  4. Java实现POS打印机自定义无驱打印

    Java实现POS打印机自定义无驱打印 热敏打印机使用越来越广泛,而安装驱动相当复杂,万幸的是,几乎所有的热敏打印机都支持ESC/P指令,参考网络上一些资料后,在此整理了一份自定义打印的方案 • 打印 ...

  5. Java使用POS打印机(无驱)

    使用原因:应项目要求,需要使用打印机,但是如果使用Windows驱动来实现打印,在某些条件下会发生网络堵塞等,而且没有提示,所以为了确保信息的完整,避免数据丢失.我们使用无驱打印(直接写端口的方法), ...

  6. C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)【转】

    原文地址:http://blog.csdn.net/ldljlq/article/details/7338772 在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇 ...

  7. PHP控制连接打印机

    一.需求 使用PHP控制连接打印机 现场实时连续打印动态数据 二.配置 php运行环境正确安装(Apache|Nginx + PHP) 下载与php版本对应的php_printer.dll扩展 扩展文 ...

  8. C# 网络打印机ESC指令打印小票

    public void SendSocketMsg(String ip, int port, int times, byte[] data) { try { byte[] mData; ) { mDa ...

  9. Atitit.收银系统pos 以及打印功能的行业标准

    Atitit.收银系统pos 以及打印功能的行业标准 1. ESC指令序列 Escape指令序列不同于ESC/POS指令 1 2. 打印标准OPOS POSPrinter 与 CashDrawer 驱 ...

随机推荐

  1. 网络编程学习笔记:linux下的socket编程

    socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...

  2. ssh 使用密钥与登录进行远程cp

    scp -P 50000 -i abc.pem  ubuntu@10.223.191.105://srv/log/webserver/main/nginx.access.2015-08-07.log ...

  3. laravel 在windows中使用一键安装包步骤

    安装 PHP 注意一:Laravel 5.0 开始对 PHP 版本的要求是 >=5.4,Laravel 5.1 要求 PHP 版本 >=5.5.9,所以,建议大家尽量安装 5.5.x 的最 ...

  4. l段子

    段子简介 L段子起源.L段子是开发者根据市场调查, 用户可在等候列车,飞机,或在公交车上无 聊之余使用本应用.打发无聊的时间,分为段 子,图片,活动和个人中心,用户可根据自己 喜好进入不同的区域.段子 ...

  5. swift:谈谈swift几种常见属性的区别

    一.前奏 Swift作为一门新语言,经过几年的发展,逐渐趋于完善,目前已经更新到3.0版本,它汇集许多其他语言的特点,例如JS.Paython.C++等,完全区别于OC.个人感觉它没有完全的OOP和O ...

  6. 使用WKWebView遇到的坑

    苹果从iOS8开始推出了WKWebView,大有替换UIWebView的意思(尽管Xcode中还没给UIWebView标记过期版本),所以决定将项目进行适配,iOS8及以上版本,改用WKWebView ...

  7. 使用git版本控制器C#工程,git托管到GitHub和visual studio on line

    类比TFS, 托管到了VS online,为私有.GitHub上托管的代码为开源. 新建工程选择版本控制器"Git" VS online: 本地: GitHub,下载github ...

  8. tomcat 格式化输出到kafka

    cat /data/tomcat/conf/server.xml <Valve className="org.apache.catalina.valves.AccessLogValve ...

  9. js 将json字符串转换为json对象的方法解析

    推荐: var obj = eval('(' + str + ')'); var last=JSON.stringify(obj); //将JSON对象转化为string字符 例如: JSON字符串: ...

  10. Android四大核心组件之ContentProvider

    实验内容 学习ContextProvider用法 编码实现简单ContextProvider功能 实验要求 通过简单代码了解ContextProvider功能和用法 实验步骤 ContextProvi ...