【转】C#使用ESC指令控制POS打印机打印小票
- .前言
- C#打印小票可以与普通打印机一样,调用PrintDocument实现。也可以发送标注你的ESC指令实现。由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的pos打印机,并且无法发送控制指令实现pos打印机的切纸、走纸等动作。因此个人建议使用ESC指令进行打印会更通用。
- 本类需要调用 ImageProcessor.cs
- .POS机打印小票ReceiptHelper
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Drawing;
- using System.Management;
- using System.IO;
- using LaisonTech.MediaLib;
- using LaisonTech.CommonBLL;
- using Microsoft.Win32.SafeHandles;
- namespace LaisonTech.MediaLib
- {
- #region 结构体定义
- [StructLayout(LayoutKind.Sequential)]
- public struct OVERLAPPED
- {
- int Internal;
- int InternalHigh;
- int Offset;
- int OffSetHigh;
- int hEvent;
- };
- [StructLayout(LayoutKind.Sequential)]
- public struct PRINTER_DEFAULTS
- {
- public int pDatatype;
- public int pDevMode;
- public int DesiredAccess;
- }
- /// <summary>
- /// 对齐方式
- /// </summary>
- public enum eTextAlignMode
- {
- Left = ,
- Middle = ,
- Right =
- }
- #endregion
- /// <summary>
- /// 小票打印类
- /// 使用方法:
- /// 1 GetPrinterList获取已经安装的所有打印机列表.
- /// Open 打开指定打印机
- /// 2 控制打印机动作、执行打印内容之前,必须先调用StartPrint,准备向打印机发送控制指令
- /// 3 调用SetLeft, SetBold, SetAlignMode, SetFontSize ... ...设置打印参数
- /// 4 PrintText 打印内容.注意:打印该行内容后会自动换行(本类会在该行内容末尾添加一个换行符)
- /// PrintImageFile 或 PrintBitMap打印图片
- /// 5 控制指令和打印内容都发送完毕后,调用 EndPrint执行真正打印动作
- /// 6 退出程序前调用Close
- /// </summary>
- public class ReceiptHelper
- {
- #region 指令定义
- private static Byte[] Const_Init = new byte[] { 0x1B, 0x40,
- 0x20, 0x20, 0x20, 0x0A,
- 0x1B, 0x64,0x10};
- //设置左边距
- private const string Const_SetLeft = "1D 4C ";
- //设置粗体
- private const string Const_SetBold = "1B 45 ";
- private const String Const_Bold_YES = "";
- private const String Const_Bold_NO = "";
- //设置对齐方式
- private const string Const_SetAlign = "1B 61 ";
- private const String Const_Align_Left = "";
- private const String Const_Align_Middle = "";
- private const String Const_Align_Right = "";
- //设置字体大小,与 SetBigFont 不能同时使用
- private const string Const_SetFontSize = "1D 21 ";
- //设置是否大字体,等同于 SetFontSize = 2
- //private const String Const_SetBigFontBold = "1B 21 38";
- //private const String Const_SetBigFontNotBold = "1B 21 30";
- //private const String Const_SetCancelBigFont = "1B 21 00";
- /// <summary>
- /// 打印并走纸
- /// </summary>
- private static Byte[] Const_Cmd_Print = new byte[] { 0x1B, 0x4A, 0x00 };
- //走纸
- private const string Const_FeedForward = "1B 4A ";
- private const string Const_FeedBack = "1B 6A ";
- //切纸
- private static Byte[] Const_SetCut = new byte[] { 0x1D, 0x56, 0x30};
- //查询打印机状态
- private static Byte[] Const_QueryID = new byte[] { 0x1D, 0x67, 0x61};
- //回复帧以 ID 开头
- private static String Const_ResponseQueryID = "ID";
- /// <summary>
- /// 设置图标的指令
- /// </summary>
- private static Byte[] Const_SetImageCommand = new Byte[] { 0x1B, 0x2A, 0x21 };
- #endregion
- #region 常量定义
- /// <summary>
- /// 最大字体大小
- /// </summary>
- public const Int32 Const_MaxFontSize = ;
- /// <summary>
- /// 最大走纸距离
- /// </summary>
- public const Int32 Const_MaxFeedLength = ;
- /// <summary>
- /// 最大高宽
- /// </summary>
- public const Int32 Const_MaxImageLength = ;
- /// <summary>
- /// 每次通信最多打印的行数
- /// </summary>
- public const Int32 Const_OncePrintRowCount = ;
- public const Int32 Const_BrightnessGate = ;
- /// <summary>
- /// 无效句柄
- /// </summary>
- public const Int32 Const_InvalidHandle = -;
- #endregion
- #region 私有成员
- /// <summary>
- /// 打印机句柄
- /// </summary>
- private int m_Handle = -;
- /// <summary>
- /// 是否已经初始化
- /// </summary>
- private Boolean m_Inited = false;
- #endregion
- #region 私有函数
- [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
- out Int32 hPrinter, IntPtr pd);
- [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool StartDocPrinter(Int32 hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
- [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool EndDocPrinter(Int32 hPrinter);
- [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool StartPagePrinter(Int32 hPrinter);
- [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool EndPagePrinter(Int32 hPrinter);
- [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool WritePrinter(Int32 hPrinter, Byte[] pBytes, Int32 dwCount, out Int32 dwWritten);
- [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
- public static extern bool ClosePrinter(Int32 hPrinter);
- /// <summary>
- /// 发送指令
- /// </summary>
- /// <param name="cmd"></param>
- /// <returns></returns>
- private Boolean SendCommand(Byte[] cmd)
- {
- if (m_Handle == Const_InvalidHandle || cmd == null || cmd.Length < )
- {
- return false;
- }
- int writelen = ;
- Boolean bl = WritePrinter(m_Handle, cmd, cmd.Length, out writelen);
- if (!bl) return false;
- return (writelen >= cmd.Length);
- }
- /// <summary>
- /// 发送文本格式的指令
- /// </summary>
- /// <param name="cmd"></param>
- /// <returns></returns>
- private Boolean SendCommand(String hexstrcmd)
- {
- if (m_Handle == Const_InvalidHandle || hexstrcmd == null || hexstrcmd.Length < )
- {
- return false;
- }
- byte[] mybyte = null;
- Boolean bl = DataFormatProcessor.HexStringToBytes(hexstrcmd, out mybyte);
- bl = SendCommand(mybyte);
- return bl;
- }
- #endregion
- #region 内部处理 - 打印图片
- /// <summary>
- /// 把图片转换为指令字节,图片最大高宽不能超过480
- /// </summary>
- /// <param name="image"></param>
- /// <param name="bmpbytes"></param>
- /// <returns></returns>
- public static Boolean LoadImage(Bitmap image,
- ref Byte[] bitarray,ref Int32 datawidth,ref Int32 dataheight)
- {
- Int32 newwidth = ;
- Int32 newheight = ;
- Bitmap destimage = image;
- Boolean bl = false;
- //如果高度超过范围,或宽度超过范围,需要进行缩小
- if (image.Width > Const_MaxImageLength || image.Height > Const_MaxImageLength)
- {
- //按照高度和宽度,较大的那一边,进行缩放
- if (image.Width > image.Height)
- {
- newwidth = Const_MaxImageLength;
- newheight = (Int32)(image.Height * newwidth / (float)image.Width);
- }
- else
- {
- newheight = Const_MaxImageLength;
- newwidth = (Int32)(newheight * image.Width / (float)image.Height);
- }
- bl = ImageProcessor.ResizeImage(image, newwidth, newheight, ref destimage);
- }
- //把数据转换为字节数组
- bl = GetBitArray(image, ref bitarray, ref datawidth, ref dataheight);
- return bl;
- }
- /// <summary>
- /// 把图片转换为指令字节,图片最大高宽不能超过480
- /// 如果图片的高度不是24的整数倍,则修改为24的整数倍
- /// </summary>
- /// <param name="image"></param>
- /// <param name="bmpbytes"></param>
- /// <returns></returns>
- public static Boolean LoadImageFromFile(String imagefilename, ref Byte[] bmpbytes,
- ref Int32 width, ref Int32 height)
- {
- Bitmap img = ImageProcessor.LoadBitImage(imagefilename);
- if (img == null)
- {
- return false;
- }
- Boolean bl = LoadImage(img, ref bmpbytes, ref width, ref height);
- return bl;
- }
- /// <summary>
- /// 把图片转换为位图数组,每个字节的每个比特位,对应当前像素 是否需要打印
- /// </summary>
- /// <param name="img"></param>
- /// <param name="allbitary"></param>
- /// <returns></returns>
- public static Boolean GetBitArray(Bitmap img,
- ref Byte[] allbitary, ref Int32 width, ref Int32 height)
- {
- if (img == null)
- {
- return false;
- }
- //ESC指令格式规定:
- //1 打印图片时,每条指令最多只打印24行;不足24行的,也要用全0填充满数据字节
- //2 打印24行数据时,按照光栅模式纵向获取数据
- // 即先获取所有x=0的点(第0列)转换为3个字节;
- // 再获取所有x=1的点转换为3个字节;...直到获取到最右侧一列的点
- //3 打印完当前24行数据后,再获取后续24行的数据内容,直到所有的数据获取完毕
- //获取亮度数组
- Boolean[] briary = null;
- Boolean bl = ImageProcessor.ToBooleanArray(img, Const_BrightnessGate, ref briary);
- if (!bl)
- {
- return false;
- }
- height = img.Height;//如果图像高度不是24整数倍,设置为24的整数倍
- if (height % Const_OncePrintRowCount != )
- {
- height = height + Const_OncePrintRowCount - height % Const_OncePrintRowCount;
- }
- width = img.Width;//如果图像宽度不是8的整数倍,设置为8的整数倍
- if (width % != )
- {
- width = width + - width % ;
- }
- Int32 bytelen = height * width / ;//每个像素对应1个比特位,因此总字节数=像素位数/8
- allbitary = new Byte[bytelen];
- Int32 byteidxInCol = ;//当前列里首个像素,在目标字节数组里的下标
- Int32 byteidx = ;//当前像素在目标数组里的字节下标
- Int32 bitidx = ;//当前像素在目标数组里当前字节里的比特位下标
- Int32 pixidxInCol = ;//当前像素在当前列里的第几个位置
- Int32 pixidx = ;//当前像素在原始图片里的下标
- Int32 rowidx = ; //当前 处理的像素点所在行,不能超过 图像高度
- Int32 curprocrows = ;//当前需要处理的行数量
- while (rowidx < height)
- {
- //按照纵向次序,把当前列的24个数据,转换为3个字节
- for (Int32 colidx = ; colidx < img.Width; ++colidx)
- {
- //如果当前还剩余超过24行没处理,处理24行
- if (rowidx + Const_OncePrintRowCount <= img.Height)
- {
- curprocrows = Const_OncePrintRowCount;
- }
- else
- {
- //已经不足24行,只处理剩余行数
- curprocrows = img.Height - rowidx;
- }
- pixidxInCol = ; //本列里从像素0开始处理
- for (Int32 y = rowidx; y < rowidx + curprocrows; ++y)
- {
- //原始图片里像素位置
- pixidx = y * img.Width + colidx;
- //获取当前像素的亮度值.如果当前像素是黑点,需要把数组里的对应比特位设置为1
- if (briary[pixidx])
- {
- bitidx = - pixidxInCol % ;//最高比特位对应首个像素.最低比特位对应末个像素
- byteidx = byteidxInCol + pixidxInCol / ; //由于最后一段可能不足24行,因此不能使用byteidx++
- DataFormatProcessor.SetBitValue(bitidx, true, ref allbitary[byteidx]);
- }
- pixidxInCol++;
- }
- byteidxInCol += ;//每列固定24个像素,3个字节
- }
- rowidx += Const_OncePrintRowCount;
- }
- return true;
- }
- #endregion
- #region 公开函数
- private static ReceiptHelper m_instance = new ReceiptHelper();
- /// <summary>
- /// 当前使用的打印机名称
- /// </summary>
- public String PrinterName
- {
- get;private set;
- }
- /// <summary>
- /// 单件模式
- /// </summary>
- /// <returns></returns>
- public static ReceiptHelper GetInstance()
- {
- return m_instance;
- }
- /// <summary>
- /// 获取本机安装的所有打印机
- /// </summary>
- /// <returns></returns>
- public static List<String> GetPrinterList()
- {
- List<String> ret = new List<String>();
- if (PrinterSettings.InstalledPrinters.Count < )
- {
- return ret;
- }
- foreach (String printername in PrinterSettings.InstalledPrinters)
- {
- ret.Add(printername);
- }
- return ret;
- }
- /// <summary>
- /// 打开打印机
- /// </summary>
- /// <param name="printername"></param>
- /// <returns></returns>
- public Boolean Open(String printername)
- {
- if (m_Inited)
- {
- return true;
- }
- Boolean bl = OpenPrinter(printername.Normalize(), out m_Handle, IntPtr.Zero);
- m_Inited = (bl && m_Handle != );
- return true;
- }
- /// <summary>
- /// 开始打印,在打印之前必须调用此函数
- /// </summary>
- /// <returns></returns>
- public Boolean StartPrint()
- {
- if (!m_Inited)
- {
- return false;
- }
- DOCINFOA di = new DOCINFOA();
- di.pDocName = "My C#.NET RAW Document";
- di.pDataType = "RAW";
- //Start a document.
- Boolean bl = StartDocPrinter(m_Handle, , di);
- if (!bl)
- {
- return false;
- }
- // Start a page.
- bl = StartPagePrinter(m_Handle);
- return bl;
- }
- /// <summary>
- /// 结束打印,在打印结束之后必须调用此函数
- /// </summary>
- /// <returns></returns>
- public Boolean EndPrint()
- {
- if (!m_Inited)
- {
- return false;
- }
- Boolean bl = EndPagePrinter(m_Handle);
- bl = EndDocPrinter(m_Handle);
- return bl;
- }
- /// <summary>
- /// 销毁
- /// </summary>
- /// <returns></returns>
- public Boolean Close()
- {
- if (!m_Inited)
- {
- return true;
- }
- m_Inited = false;
- //关闭设备句柄
- ClosePrinter(m_Handle);
- m_Handle = -;
- return true;
- }
- /// <summary>
- /// 打印文本.在调用本函数之前必须先调用正确的 设置字体、左边距
- /// </summary>
- /// <param name="content"></param>
- /// <returns></returns>
- public Boolean PrintText(String content)
- {
- if (!m_Inited)
- {
- return false;
- }
- byte[] bytes = null;
- if (content.Length < )
- {
- content = " ";
- }
- if (content[content.Length - ] != (char)0x0D &&
- content[content.Length - ] != (char)0x0A)
- {
- content = content + (char)0x0A;
- }
- bytes = DataFormatProcessor.StringToBytes(content);
- bool bl = SendCommand(bytes);
- return bl;
- }
- /// <summary>
- /// 设置对齐方式
- /// </summary>
- /// <param name="left"></param>
- /// <returns></returns>
- public bool SetAlignMode(eTextAlignMode alignmode)
- {
- if (!m_Inited)
- {
- return false;
- }
- String code = String.Empty;
- switch (alignmode)
- {
- case eTextAlignMode.Left:
- code = Const_Align_Left;
- break;
- case eTextAlignMode.Middle:
- code = Const_Align_Middle;
- break;
- case eTextAlignMode.Right:
- code = Const_Align_Right;
- break;
- default:
- code = Const_Align_Left;
- break;
- }
- //注意:先低字节后高字节
- string str = Const_SetAlign + code;
- bool bl = SendCommand(str);
- return bl;
- }
- /// <summary>
- /// 设置左边距
- /// </summary>
- /// <param name="left"></param>
- /// <returns></returns>
- public bool SetLeft(int left)
- {
- if (!m_Inited)
- {
- return false;
- }
- //注意:先低字节后高字节
- String hexstr = left.ToString("X4");
- string str = Const_SetLeft + hexstr.Substring(, ) + hexstr.Substring(, );
- bool bl = SendCommand(str);
- return bl;
- }
- /// <summary>
- /// 设置粗体
- /// </summary>
- /// <param name="bold"></param>
- /// <returns></returns>
- public Boolean SetBold(Boolean bold)
- {
- if (!m_Inited)
- {
- return false;
- }
- //注意:先低字节后高字节
- String str = String.Empty;
- if (bold)
- {
- str = Const_SetBold + Const_Bold_YES;
- }
- else
- {
- str = Const_SetBold + Const_Bold_NO;
- }
- bool bl = SendCommand(str);
- return bl;
- }
- /// <summary>
- /// 切纸
- /// </summary>
- /// <returns></returns>
- public bool Cut()
- {
- if (!m_Inited)
- {
- return false;
- }
- bool bl = SendCommand(Const_SetCut);
- return bl;
- }
- /// <summary>
- /// 打印图片
- /// </summary>
- /// <param name="bitmap"></param>
- /// <returns></returns>
- public bool PrintImageFile(String imgfilename)
- {
- if (!m_Inited)
- {
- return false;
- }
- Bitmap img = ImageProcessor.LoadBitImage(imgfilename);
- if (img == null)
- {
- return false;
- }
- Boolean bl = PrintBitmap(img);
- return bl;
- }
- /// <summary>
- /// 打印图片
- /// </summary>
- /// <param name="bitmap"></param>
- /// <returns></returns>
- public bool PrintBitmap(Bitmap bitmap)
- {
- if (!m_Inited)
- {
- return false;
- }
- if (bitmap == null ||
- bitmap.Width > Const_MaxImageLength ||
- bitmap.Height > Const_MaxImageLength)
- {
- return false;
- }
- Byte[] bitary = null;
- Int32 width = ;
- Int32 height = ;
- Boolean bl = GetBitArray(bitmap, ref bitary, ref width, ref height);
- bl = PrintBitmapBytes(bitary, bitmap.Width, bitmap.Height);
- return bl;
- }
- /// <summary>
- /// 打印图片
- /// </summary>
- /// <param name="bitmap"></param>
- /// <returns></returns>
- public bool PrintBitmapBytes(Byte[] imgbitarray, Int32 width, Int32 height)
- {
- if (!m_Inited)
- {
- return false;
- }
- Int32 bytes = width * height / ;
- //检查是否尺寸符合要求
- if (width > Const_MaxImageLength || height > Const_MaxFeedLength ||
- width < || height < ||
- imgbitarray == null)
- {
- return false;
- }
- //每次获取24行的数据进行发送,这24行的字节数
- Int32 blockbytes = width * Const_OncePrintRowCount / ;
- if (blockbytes < )
- {
- return false;
- }
- Boolean bl = false;
- //一共需要发送的块数量
- Int32 blocks = imgbitarray.Length / blockbytes;
- //每次发送的数据字节数 = 1B 2A 21 2字节长度 + 数据内容
- Byte[] cmdbytes = new Byte[ + blockbytes];
- //指令
- Array.Copy(Const_SetImageCommand, cmdbytes, );
- //数据长度,即 每行的点数
- DataFormatProcessor.Int16ToBytes(width, ref cmdbytes, );
- //数据内容
- for (Int32 blockidx = ; blockidx < blocks; ++blockidx)
- {
- Array.Copy(imgbitarray, blockidx * blockbytes, cmdbytes, , blockbytes);
- //发送当前指令
- bl = SendCommand(cmdbytes);
- if (!bl) return false;
- //休眠20毫秒
- Thread.Sleep();
- //发送 打印指令
- bl = SendCommand(Const_Cmd_Print);
- if (!bl) return false;
- }
- return bl;
- }
- /// <summary>
- /// 走纸
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- public bool Feed(int length)
- {
- if (!m_Inited)
- {
- return false;
- }
- if (length < )
- length = ;
- if (length > Const_MaxFeedLength)
- {
- length = Const_MaxFeedLength;
- }
- string len = length.ToString("X2");
- len = Const_FeedForward + len;
- bool bl = SendCommand(len);
- return bl;
- }
- /// <summary>
- /// 回退走纸
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- public bool FeedBack(int length)
- {
- if (!m_Inited)
- {
- return false;
- }
- if (length < )
- length = ;
- if (length > Const_MaxFeedLength)
- {
- length = Const_MaxFeedLength;
- }
- string len = length.ToString("X2");
- len = Const_FeedBack + len;
- bool bl = SendCommand(len);
- return bl;
- }
- /// <summary>
- /// 设置字体大小.本函数不可与SetBigFont同时使用
- /// </summary>
- /// <param name="sizerate">大小倍率,取值范围 1 - 8</param>
- /// <returns></returns>
- public bool SetFontSize(Int32 sizerate)
- {
- if (!m_Inited)
- {
- return false;
- }
- if (sizerate < )
- {
- sizerate = ;
- }
- if (sizerate > Const_MaxFontSize)
- {
- sizerate = Const_MaxFontSize;
- }
- sizerate--;
- String sizecodestr = Const_SetFontSize + sizerate.ToString("X1") + sizerate.ToString("X1");
- bool bl = SendCommand(sizecodestr);
- return bl;
- }
- #endregion
- }
- }
- .图像处理 ImageProcessor
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Drawing;
- using LaisonTech.CommonBLL;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using AForge.Imaging.Filters;
- namespace LaisonTech.MediaLib
- {
- /// <summary>
- /// 图片格式
- /// </summary>
- public enum ePictureFileFormat
- {
- Bmp = ,
- Gif = ,
- Icon = ,
- Jpeg = ,
- Png = ,
- }
- /// <summary>
- /// 转为灰度图像的方式
- /// </summary>
- public enum eGrayMode
- {
- /// <summary>
- /// 算数平均
- /// </summary>
- ArithmeticAverage = ,
- /// <summary>
- /// 加权平均
- /// </summary>
- WeightedAverage = ,
- }
- /// <summary>
- /// 比较2个图片的指定区域范围,像素的相同类型
- /// </summary>
- public enum eAreaDifferentType
- {
- /// <summary>
- /// 所有像素都相同
- /// </summary>
- AllSame = ,
- /// <summary>
- /// 所有像素都不同
- /// </summary>
- AllDifferent = ,
- /// <summary>
- /// 部分相同部分不同
- /// </summary>
- Partial = ,
- }
- /// <summary>
- /// 图片文件处理
- /// </summary>
- public class ImageProcessor
- {
- #region 常量定义
- public const Byte Const_BrightnessWhite = ;
- public const Byte Const_BrightnessBlack = ;
- /// <summary>
- /// 比较结果的图片里,亮度相同部分的填充颜色
- /// </summary>
- public static Color Const_SameBrightnessColor = Color.Black;
- /// <summary>
- /// 比较结果的图片里,亮度相同部分的填充颜色
- /// </summary>
- public static Color Const_DifferentBrightnessColor = Color.White;
- public const Byte Const_BlackBrightness = ;
- public const Byte Const_WhiteBrightness = ;
- public const Int32 Const_MaxBrightness = ;
- public const Int32 Const_MinBrightness = -;
- /// <summary>
- /// 亮度的中间值
- /// </summary>
- public const Int32 Const_MiddleBrightness = ;
- #endregion
- #region 屏幕截图,打印
- /// <summary>
- /// 获取屏幕分辨率
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- public static void GetScreenSize(ref Int32 width, ref Int32 height)
- {
- height = Screen.PrimaryScreen.Bounds.Height;
- width = Screen.PrimaryScreen.Bounds.Width;
- }
- /// <summary>
- ///截图指定控件上显示的内容
- /// </summary>
- /// <param name="ctrl"></param>
- /// <returns></returns>
- public static Image CaptureControlImage(Control ctrl)
- {
- if (ctrl == null)
- {
- return null;
- }
- Control parent = ctrl;
- if (ctrl.Parent != null)
- {
- parent = ctrl.Parent;
- }
- Point screenPoint = parent.PointToScreen(ctrl.Location);
- Image ret = new Bitmap(ctrl.Width, ctrl.Height);
- Graphics g = Graphics.FromImage(ret);
- g.CopyFromScreen(screenPoint.X, screenPoint.Y,
- , , ctrl.Size);
- g.DrawImage(ret, , );
- return ret;
- }
- #endregion
- #region 装载图片
- /// <summary>
- /// 装载图像文件
- /// </summary>
- /// <param name="filename"></param>
- /// <returns></returns>
- public static Image LoadImage(String filename)
- {
- //Boolean bl = FileProcessor.FileExist(filename);
- //if (!bl)
- //{
- // return null;
- //}
- //Bitmap image = (Bitmap)Bitmap.FromFile(filename);
- //return image;
- //以上方法会导致图片文件被锁定,无法删除移动
- Byte[] photodata = null;
- Boolean bl = FileProcessor.FileExist(filename);
- if (!bl)
- {
- return null;
- }
- bl = FileProcessor.ReadFileBytes(filename, out photodata);
- if (!bl)
- {
- return null;
- }
- MemoryStream ms = null;
- Image myImage = null;
- try
- {
- ms = new MemoryStream(photodata);
- myImage = Bitmap.FromStream(ms);
- ms.Close();
- }
- catch (System.Exception ex)
- {
- Console.WriteLine("LoadImage error:" + ex.Message);
- myImage = null;
- }
- return myImage;
- }
- /// <summary>
- /// 装载图像文件
- /// </summary>
- /// <param name="filename"></param>
- /// <returns></returns>
- public static Bitmap LoadBitImage(String filename)
- {
- Bitmap ret = (Bitmap)LoadImage(filename);
- return ret;
- }
- /// <summary>
- /// 保存图片到指定路径
- /// </summary>
- /// <param name="img"></param>
- /// <param name="filename"></param>
- /// <returns></returns>
- public static Boolean SaveImage(Image img, String filename)
- {
- FileProcessor.DeleteFile(filename);
- if (img == null)
- {
- return false;
- }
- //获取保存图片的路径,如果路径不存在,新建
- String folder = FileProcessor.GetDirectoryName(filename);
- if (!FileProcessor.DirectoryExist(folder))
- {
- FileProcessor.CreateDirectory(folder);
- }
- img.Save(filename);
- Boolean bl = FileProcessor.FileExist(filename);
- return bl;
- }
- #endregion
- #region 转换图片格式
- /// <summary>
- /// 转换图片格式
- /// </summary>
- /// <param name="bmpfilename"></param>
- /// <param name="jpgfilename"></param>
- /// <returns></returns>
- public static Boolean BmpToJpg(String bmpfilename, String jpgfilename)
- {
- Boolean bl = ChangeFileFormat(bmpfilename, jpgfilename, ePictureFileFormat.Jpeg);
- return bl;
- }
- /// <summary>
- /// 转换图片格式
- /// </summary>
- /// <param name="srcfilename"></param>
- /// <param name="destfilename"></param>
- /// <param name="destformat"></param>
- /// <returns></returns>
- public static Boolean ChangeFileFormat(String srcfilename, String destfilename, ePictureFileFormat destformat)
- {
- Boolean bl = FileProcessor.FileExist(srcfilename);
- if (!bl)
- {
- return false;
- }
- Image image = Image.FromFile(srcfilename);
- ImageFormat IFMT = null;
- switch (destformat)
- {
- case ePictureFileFormat.Bmp:
- IFMT = ImageFormat.Bmp;
- break;
- case ePictureFileFormat.Gif:
- IFMT = ImageFormat.Gif;
- break;
- case ePictureFileFormat.Icon:
- IFMT = ImageFormat.Icon;
- break;
- case ePictureFileFormat.Jpeg:
- IFMT = ImageFormat.Jpeg;
- break;
- case ePictureFileFormat.Png:
- IFMT = ImageFormat.Png;
- break;
- default:
- IFMT = ImageFormat.Jpeg;
- break;
- }
- image.Save(destfilename, IFMT);
- image.Dispose();
- bl = FileProcessor.FileExist(destfilename);
- if (!bl)
- {
- return false;
- }
- Int32 filelen = FileProcessor.GetFileLength(destfilename);
- return (filelen > );
- }
- /// <summary>
- /// 变成黑白图
- /// </summary>
- /// <param name="srcbitmap">原始图</param>
- /// <param name="mode">模式。0:加权平均 1:算数平均</param>
- /// <returns></returns>
- public static Bitmap ToGray(Bitmap bitmap, eGrayMode mode = eGrayMode.ArithmeticAverage)
- {
- if (bitmap == null)
- {
- return null;
- }
- int width = bitmap.Width;
- int height = bitmap.Height;
- byte newColor = ;
- try
- {
- BitmapData srcData = bitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* curpix = (byte*)srcData.Scan0.ToPointer();
- if (mode == eGrayMode.ArithmeticAverage)// 算数平均
- {
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- newColor = (byte)((float)(curpix[] + curpix[] + curpix[]) / 3.0f);
- curpix[] = newColor;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix += ;
- }
- curpix += srcData.Stride - width * ;
- }
- }
- else
- {
- // 加权平均
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- newColor = (byte)((float)curpix[] * 0.114f + (float)curpix[] * 0.587f + (float)curpix[] * 0.299f);
- curpix[] = newColor;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix += ;
- }
- curpix += srcData.Stride - width * ;
- }
- }
- bitmap.UnlockBits(srcData);
- }
- }
- catch
- {
- bitmap = null;
- }
- return bitmap;
- }
- /// <summary>
- /// 获取一幅图片对应的所有像素亮度数组
- /// </summary>
- /// <param name="bitmap">原始图</param>
- /// <param name="brightnessary">亮度值数组</param>
- /// <param name="mode">模式。0:加权平均 1:算数平均</param>
- /// <returns></returns>
- public static Boolean GetImageBrightness(Bitmap bitmap, ref Byte[] brightnessary,
- eGrayMode mode = eGrayMode.WeightedAverage)
- {
- if (bitmap == null)
- {
- return false;
- }
- int width = bitmap.Width;
- int height = bitmap.Height;
- if (width < || height < )
- {
- return false;
- }
- brightnessary = new Byte[width * height];
- Boolean bl = false;
- Int32 rowredundancy = ;//每一行像素,对应的数组长度 与 实际像素点数的差值
- Int32 pixidx = ;//像素下标
- try
- {
- BitmapData srcData = bitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- rowredundancy = srcData.Stride - width * ;//每行末尾还有这么多的冗余字节
- unsafe
- {
- byte* curpix = (byte*)srcData.Scan0.ToPointer();
- if (mode == eGrayMode.ArithmeticAverage)// 算数平均
- {
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- brightnessary[pixidx] = (byte)((float)(curpix[] + curpix[] + curpix[]) / 3.0f);
- ++pixidx;
- curpix += ;
- }
- curpix += rowredundancy;
- }
- }
- else
- {
- // 加权平均
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- brightnessary[pixidx] = (byte)((float)curpix[] * 0.114f + (float)curpix[] * 0.587f + (float)curpix[] * 0.299f);
- ++pixidx;
- curpix += ;
- }
- curpix += rowredundancy;
- }
- }
- bitmap.UnlockBits(srcData);
- }
- bl = true;
- }
- catch(Exception ex)
- {
- bl = false;
- Console.WriteLine("Get brightness ary error:" + ex.Message);
- }
- return bl;
- }
- /// <summary>
- /// 变成黑白图,每个元素都是一个像素的亮度
- /// </summary>
- /// <param name=" bitmap ">原始图</param>
- /// <param name=" graybitmap ">黑白图</param>
- /// <param name=" brightnessbytes ">黑白所有像素点亮度</param>
- /// <param name="mode">模式。0:加权平均 1:算数平均</param>
- /// <returns></returns>
- public static Boolean ToGray(Bitmap bitmap, ref Bitmap graybitmap, ref Byte[] brightnessbytes,
- eGrayMode mode = eGrayMode.WeightedAverage)
- {
- if (bitmap == null)
- {
- return false;
- }
- brightnessbytes = new Byte[bitmap.Width * bitmap.Height];
- int width = bitmap.Width;
- int height = bitmap.Height;
- //Clone 可能引发 GDI+异常
- graybitmap = new Bitmap(bitmap);
- byte newColor = ;
- Int32 bytesidx = ;
- Boolean bl = false;
- try
- {
- BitmapData srcData = graybitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* curpix = (byte*)srcData.Scan0.ToPointer();
- if (mode == eGrayMode.ArithmeticAverage)// 算数平均
- {
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- newColor = (byte)((float)(curpix[] + curpix[] + curpix[]) / 3.0f);
- brightnessbytes[bytesidx] = newColor;
- ++bytesidx;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix += ;
- }
- curpix += srcData.Stride - width * ;
- }
- }
- else
- {
- // 加权平均
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- newColor = (byte)((float)curpix[] * 0.114f + (float)curpix[] * 0.587f + (float)curpix[] * 0.299f);
- brightnessbytes[bytesidx] = newColor;
- ++bytesidx;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix[] = newColor;
- curpix += ;
- }
- curpix += srcData.Stride - width * ;
- }
- }
- graybitmap.UnlockBits(srcData);
- }
- bl = true;
- }
- catch(Exception ex)
- {
- graybitmap = null;
- Console.WriteLine("ToGray error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 把图片转换为非黑即白的二色图.
- /// </summary>
- /// <param name="bitmap">原始图</param>
- /// <param name="brightnessGate">亮度门限.超过此亮度认为白点,否则认为黑点</param>
- /// <param name="bitary">每个像素点是否为黑点的数组</param>
- /// <param name="trueAsblack">true-每个元素黑点为true,白点为false; false-每个元素白点为true,黑点为false</param>
- /// <returns></returns>
- public static Boolean ToBooleanArray(Bitmap bitmap, Byte brightnessGate, ref Boolean[] bitary, Boolean trueAsblack = true)
- {
- if (bitmap == null)
- {
- return false;
- }
- bitary = new Boolean[bitmap.Width * bitmap.Height];
- int width = bitmap.Width;
- int height = bitmap.Height;
- byte curcolor = ;
- Int32 pixidx = ;
- Boolean bl = false;
- try
- {
- BitmapData srcData = bitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* curpix = (byte*)srcData.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- curcolor = (byte)((float)(curpix[] + curpix[] + curpix[]) / 3.0f);
- if (trueAsblack)//true为黑点
- {
- bitary[pixidx] = (curcolor < brightnessGate);
- }
- else
- {
- //true为白点
- bitary[pixidx] = (curcolor > brightnessGate);
- }
- ++pixidx;
- curpix += ;
- }
- curpix += srcData.Stride - width * ;
- }
- bitmap.UnlockBits(srcData);
- }
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("ToGray error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 亮度差数组变成bool数组.true表示亮度不同,false表示亮度相同
- /// </summary>
- /// <param name="bridiffary">亮度差数组</param>
- /// <param name="brightnessGate">亮度门限.超过此亮度认为白点,否则认为黑点</param>
- /// <returns></returns>
- public static Boolean BrightnessToBoolean(Byte[] bridiffary, Byte brightnessGate, ref Boolean[] boolary)
- {
- if (bridiffary == null || bridiffary.Length < )
- {
- return false;
- }
- boolary = new Boolean[bridiffary.Length];
- for (Int32 idx = ; idx < bridiffary.Length; ++idx)
- {
- boolary[idx] = (bridiffary[idx] > brightnessGate);
- }
- return true;
- }
- #endregion
- #region 图片调整
- /// <summary>
- /// 调整亮度
- /// </summary>
- /// <param name="bitmap">原始图</param>
- /// <param name="degree">亮度,取值范围-255 - 255</param>
- /// <returns></returns>
- public static Bitmap SetBrightness(Bitmap srcbitmap, int brightnessOffset)
- {
- if (srcbitmap == null)
- {
- return null;
- }
- CommonCompute.SetInt32Range(ref brightnessOffset, Const_MinBrightness, Const_MaxBrightness);
- int width = srcbitmap.Width;
- int height = srcbitmap.Height;
- Bitmap bitmap = (Bitmap)srcbitmap.Clone();
- try
- {
- BitmapData data = bitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* curpix = (byte*)data.Scan0.ToPointer();
- Int32 curcolor = ;
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- curcolor = curpix[] + brightnessOffset;
- CommonCompute.SetInt32Range(ref curcolor, , Const_MaxBrightness);
- curpix[] = (byte)curcolor;
- curcolor = curpix[] + brightnessOffset;
- CommonCompute.SetInt32Range(ref curcolor, , Const_MaxBrightness);
- curpix[] = (byte)curcolor;
- curcolor = curpix[] + brightnessOffset;
- CommonCompute.SetInt32Range(ref curcolor, , Const_MaxBrightness);
- curpix[] = (byte)curcolor;
- curpix += ;
- }
- curpix += data.Stride - width * ;
- }
- }
- bitmap.UnlockBits(data);
- }
- catch
- {
- bitmap = null;
- }
- return bitmap;
- }
- /// <summary>
- /// 调整图像对比度
- /// </summary>
- /// <param name="bitmap">原始图</param>
- /// <param name="degree">对比度 0 - 100</param>
- /// <returns></returns>
- public static Bitmap SetContrast(Bitmap srcbitmap, int contrast)
- {
- if (srcbitmap == null)
- {
- return null;
- }
- //对比度取值范围,0-100
- CommonCompute.SetInt32Range(ref contrast, , );
- Int32 curcolor = ;
- Bitmap bitmap = (Bitmap)srcbitmap.Clone();
- int width = bitmap.Width;
- int height = bitmap.Height;
- //调整对比度基本思路:0时,所有像素点的亮度都设置为中间值128
- //100 时,把亮度大于128的像素,亮度设置为255;小于128的设置为0
- //即:50时,保持不变;小于50,所有点的亮度向中间值128偏移;大于50,所有点亮度值向两端偏移
- //如果当前像素点的亮度是130, 对比度为50时,结果仍然要是130,此时rate为1.0
- //对比度为100时,结果要变成255,此时rate >= 128
- //对比度为0时,结果要变成128,此时rate = 0
- //因此可知对比度与rate的对应关系
- //对比度: 0 50 100
- //rate : 0 1 127
- double rate = ;
- if (contrast == )
- {
- rate = ;
- }
- else if (contrast < )
- {
- rate = contrast / 50.0;//小于50的,对比度比率必须是纯小数,0-1 之间
- }
- else
- {
- rate = + Const_MiddleBrightness * ((contrast - 50.0) / 50.0);//大于50的,比率必须是1到128之间的值
- }
- try
- {
- BitmapData data = bitmap.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* curpix = (byte*)data.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- for (int i = ; i < ; i++) //R,G,B 3个通道
- {
- //对于 刚好亮度等于中间值的点,需要把亮度调高或调低1
- //否则将无法实现对该点 提高对比度
- if (curpix[i] == Const_MiddleBrightness)
- {
- curpix[i] = (byte)(curpix[i] + );
- }
- //调整该像素对比度
- curcolor = (Int32)(Const_MiddleBrightness + (curpix[i] - Const_MiddleBrightness) * rate);
- CommonCompute.SetInt32Range(ref curcolor, Const_MinBrightness, Const_MaxBrightness);
- curpix[i] = (byte)curcolor;
- ++curpix;
- }
- }
- curpix += data.Stride - width * ;
- }
- }
- bitmap.UnlockBits(data);
- }
- catch
- {
- bitmap = null;
- }
- return bitmap;
- }
- /// <summary>
- /// 任意角度旋转
- /// </summary>
- /// <param name="srcbitmap">原始图Bitmap</param>
- /// <param name="angle">旋转角度</param>
- /// <param name="bkColor">背景色</param>
- /// <returns>输出Bitmap</returns>
- public static Bitmap Rotate(Bitmap srcbitmap, float angle, Color bkColor)
- {
- int w = srcbitmap.Width + ;
- int h = srcbitmap.Height + ;
- PixelFormat pf;
- if (bkColor == Color.Transparent)
- {
- pf = PixelFormat.Format32bppArgb;
- }
- else
- {
- pf = srcbitmap.PixelFormat;
- }
- Bitmap tmp = new Bitmap(w, h, pf);
- Graphics g = Graphics.FromImage(tmp);
- g.Clear(bkColor);
- g.DrawImageUnscaled(srcbitmap, , );
- g.Dispose();
- GraphicsPath path = new GraphicsPath();
- path.AddRectangle(new RectangleF(0f, 0f, w, h));
- Matrix mtrx = new Matrix();
- mtrx.Rotate(angle);
- RectangleF rct = path.GetBounds(mtrx);
- Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
- g = Graphics.FromImage(dst);
- g.Clear(bkColor);
- g.TranslateTransform(-rct.X, -rct.Y);
- g.RotateTransform(angle);
- g.InterpolationMode = InterpolationMode.HighQualityBilinear;
- g.DrawImageUnscaled(tmp, , );
- g.Dispose();
- tmp.Dispose();
- return dst;
- }
- /// <summary>
- /// Gamma校正
- /// </summary>
- /// <param name="srcbitmap">输入Bitmap</param>
- /// <param name="val">[0 <-明- 1 -暗-> 2]</param>
- /// <returns>输出Bitmap</returns>
- public static Bitmap SetGamma(Bitmap srcbitmap, float val)
- {
- if (srcbitmap == null)
- {
- return null;
- }
- // 1表示无变化,就不做
- if (val == 1.0000f) return srcbitmap;
- try
- {
- Bitmap b = new Bitmap(srcbitmap.Width, srcbitmap.Height);
- Graphics g = Graphics.FromImage(b);
- ImageAttributes attr = new ImageAttributes();
- attr.SetGamma(val, ColorAdjustType.Bitmap);
- g.DrawImage(srcbitmap, new Rectangle(, , srcbitmap.Width, srcbitmap.Height), , , srcbitmap.Width, srcbitmap.Height, GraphicsUnit.Pixel, attr);
- g.Dispose();
- return b;
- }
- catch
- {
- return null;
- }
- }
- /// <summary>
- /// 重新设置图片尺寸
- /// </summary>
- /// <param name="srcbitmap">original Bitmap</param>
- /// <param name="newW">new width</param>
- /// <param name="newH">new height</param>
- /// <returns>worked bitmap</returns>
- public static Boolean ResizeImage(Bitmap srcimg, int newW, int newH, ref Bitmap destimage)
- {
- if (srcimg == null)
- {
- return false;
- }
- destimage = new Bitmap(newW, newH);
- Graphics graph = Graphics.FromImage(destimage);
- Boolean bl = true;
- try
- {
- graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
- graph.DrawImage(srcimg, new Rectangle(, , newW, newH),
- new Rectangle(, , srcimg.Width, srcimg.Height),
- GraphicsUnit.Pixel);
- graph.Dispose();
- }
- catch (Exception ex)
- {
- Console.WriteLine("ResizeImage error" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 去除噪点
- /// </summary>
- /// <param name="noisypointsize">噪点的尺寸</param>
- /// <param name="bitmap">待处理的图片信息</param>
- /// <returns></returns>
- public static Boolean RemoveNoisypoint(Int32 noisypointsize, ref Bitmap bitmap)
- {
- if (bitmap == null || noisypointsize < ||
- noisypointsize * >= bitmap.Width || noisypointsize * >= bitmap.Height)
- {
- return false;
- }
- // 创建过滤器
- BlobsFiltering blobfilter =
- new BlobsFiltering();
- // 设置过滤条件(对象长、宽至少为70)
- blobfilter.CoupledSizeFiltering = true;
- blobfilter.MinWidth = noisypointsize;
- blobfilter.MinHeight = noisypointsize;
- blobfilter.ApplyInPlace(bitmap);
- return true;
- }
- /// <summary>
- /// 把图片里指定区域的内容复制到另一个图片里
- /// </summary>
- /// <param name="srcimg"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="destimg"></param>
- /// <returns></returns>
- public static Boolean CutImage(Bitmap srcimg, Int32 x, Int32 y, Int32 width, Int32 height, ref Bitmap destimg)
- {
- if (srcimg == null || x < || y < || width < || height < ||
- x + width > srcimg.Width || y + height > srcimg.Height)
- {
- return false;
- }
- destimg = new Bitmap(width, height, PixelFormat.Format32bppArgb);
- Graphics graph = Graphics.FromImage(destimg);
- graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
- graph.DrawImage(srcimg, new Rectangle(, , width, height),
- new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
- graph.Dispose();
- return true;
- }
- #endregion
- #region 亮度处理
- /// <summary>
- /// 获取指定坐标处的亮度值
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetPixBrightness(Bitmap bitmap, Int32 x, Int32 y, eGrayMode mode, ref Byte brightness)
- {
- if (bitmap == null)
- {
- return false;
- }
- if (x < || x >= bitmap.Width ||
- y < || y >= bitmap.Height)
- {
- return false;
- }
- Color curColor = bitmap.GetPixel(x, y);
- //利用公式计算灰度值(加权平均法)
- if (mode == eGrayMode.ArithmeticAverage)
- {
- brightness = (Byte)(curColor.R * 0.299f + curColor.G * 0.587f + curColor.B * 0.114f);
- }
- else
- {
- brightness = (Byte)((curColor.R + curColor.G + curColor.B) / 3.0f);
- }
- return true;
- }
- /// <summary>
- /// 获取指定坐标处的亮度值
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetPixBrightness(Byte[] bribytes, Int32 width,Int32 height,
- Int32 x, Int32 y, ref Byte brightness)
- {
- if (bribytes == null || width < || height < ||
- x < || x >= width ||
- y < || y >= height ||
- bribytes.Length != width * height)
- {
- return false;
- }
- brightness = bribytes[y * width + x];
- return true;
- }
- /// <summary>
- /// 获取指定坐标处的亮度值
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetPixBrightnessByRate(Byte[] bribytes, Int32 width, Int32 height,
- double xRate, double yRate, ref Byte brightness)
- {
- int x = (int)(width * xRate);
- int y = (int)(height * yRate);
- if (bribytes == null || width < || height < ||
- x < || x >= width ||
- y < || y >= height ||
- bribytes.Length != width * height)
- {
- return false;
- }
- brightness = bribytes[y * width + x];
- return true;
- }
- /// <summary>
- /// 获取指定坐标处的颜色
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetPixColor(Bitmap bitmap, Int32 x, Int32 y, ref Color curColor)
- {
- if (bitmap == null)
- {
- return false;
- }
- if (x < || x >= bitmap.Width ||
- y < || y >= bitmap.Height)
- {
- return false;
- }
- curColor = bitmap.GetPixel(x, y);
- return true;
- }
- /// <summary>
- /// 获取指定坐标处的颜色
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetPixColorByRate(Bitmap bitmap, double xRate, double yRate, ref Color curColor)
- {
- if (bitmap == null)
- {
- return false;
- }
- int width = bitmap.Width;
- int height = bitmap.Height;
- int X = (int)(width * xRate);
- int Y = (int)(height * yRate);
- Boolean bl = GetPixColor(bitmap, X, Y, ref curColor);
- return bl;
- }
- /// <summary>
- /// 把颜色转换为亮度值
- /// </summary>
- /// <param name="bitmap"></param>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <returns></returns>
- public static Boolean GetBrightnessByColor(Color curColor, eGrayMode mode, ref Byte brightness)
- {
- if (curColor == null)
- {
- return false;
- }
- //利用公式计算灰度值(加权平均法)
- if (mode == eGrayMode.ArithmeticAverage)
- {
- brightness = (Byte)(curColor.R * 0.299f + curColor.G * 0.587f + curColor.B * 0.114f);
- }
- else
- {
- brightness = (Byte)((curColor.R + curColor.G + curColor.B) / 3.0f);
- }
- return true;
- }
- #endregion
- #region 图片比较
- /// <summary>
- /// 根据2个图片的亮度值,比较图片的差异部分
- /// </summary>
- /// <param name="brightnessDiff"></param>
- /// <param name="compareret"></param>
- /// <returns></returns>
- public static Boolean CompareImageBrightness(Byte brightnessDiff,
- Byte[] brightness1, Byte[] brightness2,
- ref Boolean[] diffPixArray)
- {
- if (brightness1 == null || brightness2 == null ||
- brightness1.Length < || brightness2.Length < ||
- brightness1.Length != brightness2.Length)
- {
- return false;
- }
- Int32 arylen = brightness1.Length;
- diffPixArray = new Boolean[brightness1.Length];
- Byte bri1 = ;
- Byte bri2 = ;
- for (Int32 byteidx = ; byteidx < arylen; ++byteidx)
- {
- bri1 = brightness1[byteidx];
- bri2 = brightness2[byteidx];
- //亮度差超过指定范围
- if (bri1 >= bri2 + brightnessDiff ||
- bri2 >= bri1 + brightnessDiff)
- {
- diffPixArray[byteidx] = true;
- }
- }
- return true;
- }
- /// <summary>
- /// 把2个图片的尺寸设置为一样大
- /// </summary>
- /// <param name="image1"></param>
- /// <param name="image2"></param>
- /// <returns></returns>
- public static Boolean ResizeImageToSame(ref Bitmap image1, ref Bitmap image2)
- {
- if (image1 == null || image2 == null ||
- image1.Width == || image1.Height == ||
- image2.Width == || image2.Height == )
- {
- return false;
- }
- //如果2个图片尺寸不一样,把大的尺寸压缩小了再比较
- Boolean bl = false;
- Bitmap tmpimg = null;
- if (image1.Width > image2.Width && image1.Height < image2.Height)
- {
- return false;
- }
- if (image1.Width < image2.Width && image1.Height > image2.Height)
- {
- return false;
- }
- //image1 比较大,把image2放大到 与1一样大
- if (image1.Width > image2.Width && image1.Height > image2.Height)
- {
- bl = ResizeImage(image2, image1.Width, image1.Height, ref tmpimg);
- image2 = tmpimg;
- }
- //image 2比较大,把image1放大到 与2一样大
- if (image1.Width < image2.Width && image1.Height < image2.Height)
- {
- bl = ResizeImage(image1, image2.Width, image2.Height, ref tmpimg);
- image1 = tmpimg;
- }
- return true;
- }
- /// <summary>
- /// 根据2个图片的像素颜色值,比较图片的差异部分
- /// </summary>
- /// <param name="compareparam"></param>
- /// <param name="compareret"></param>
- /// <returns></returns>
- public static Boolean CompareImage(ImageCompareParameter compareparam,
- ref ImageCompareResult compareret)
- {
- Bitmap image1 = compareparam.Image1;
- Bitmap image2 = compareparam.Image2;
- Int32 briDiff = compareparam.BrightnessDiff;
- Color diffColor = compareparam.DifferentAreaFillColor;
- Color samecolor = compareparam.SameAreaFillColor;
- //是否需要填充相同或不同部分的像素的颜色
- Boolean filldiffcolor = (diffColor != Color.Transparent);
- Boolean fillsamecolor = (samecolor != Color.Transparent);
- //如果图片尺寸不一样,修改为一样大
- Boolean bl = ResizeImageToSame(ref image1, ref image2);
- if (!bl)
- {
- return false;
- }
- Bitmap imagediff = (Bitmap)image1.Clone();
- //不同区域的左上下右位置
- Int32 areaLeft = imagediff.Width;
- Int32 areaTop = imagediff.Height;
- Int32 areaRight = -;
- Int32 areaBottom = -;
- int width = image1.Width;
- int height = image1.Height;
- long allpixcnt = height * width;//所有像素点数量
- long diffpixcnt = ;//不同像素点数量
- long samepixcnt = ;//相同像素点数量
- //3张图片的各像素亮度数组
- Int32 briaryidx = ;
- Byte[] briary1 = new Byte[allpixcnt];
- Byte[] briary2 = new Byte[allpixcnt];
- Byte[] briaryret = new Byte[allpixcnt];
- Byte diffB = diffColor.B;
- Byte diffG = diffColor.G;
- Byte diffR = diffColor.R;
- Byte sameB = samecolor.B;
- Byte sameG = samecolor.G;
- Byte sameR = samecolor.R;
- Byte samebri = ;
- Byte diffbri = ;
- GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);
- GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);
- try
- {
- BitmapData data1 = image1.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- BitmapData data2 = image2.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- BitmapData datadiff = imagediff.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- byte bri1 = ;
- byte bri2 = ;
- //每个像素是否相同.1相同,0不同
- compareret.PixIsDifferent = new Boolean[width * height];
- //当前像素是否不同
- Boolean curpixIsdiff = false;
- unsafe
- {
- byte* curpix1 = (byte*)data1.Scan0.ToPointer();
- byte* curpix2 = (byte*)data2.Scan0.ToPointer();
- byte* curpixdiff = (byte*)datadiff.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- //利用公式计算灰度值(加权平均法)
- //按BGR的顺序存储
- bri1 = (Byte)(curpix1[] * 0.114f + curpix1[] * 0.587f + curpix1[] * 0.299f);
- bri2 = (Byte)(curpix2[] * 0.114f + curpix2[] * 0.587f + curpix2[] * 0.299f);
- //以1作为基准,比较1和2之间的差距,如果超过阀值,认为当前像素有差异
- //否则认为当前像素没有差异
- curpixIsdiff = false;
- if (bri1 >= bri2 + briDiff ||
- bri2 >= bri1 + briDiff)
- {
- curpixIsdiff = true;
- }
- briary1[briaryidx] = bri1;
- briary2[briaryidx] = bri2;
- if (curpixIsdiff) //如果有差异,设置图像1里的当前像素为 不同颜色
- {
- if (filldiffcolor)
- {
- curpixdiff[] = diffB;
- curpixdiff[] = diffG;
- curpixdiff[] = diffR;
- }
- ++diffpixcnt;
- if (x < areaLeft) //记忆最左边的像素位置
- {
- areaLeft = x;
- }
- if (x > areaRight) //记忆最右边的像素位置
- {
- areaRight = x;
- }
- if (y < areaTop) //记忆最上边的像素位置
- {
- areaTop = y;
- }
- if (y > areaBottom) //记忆最下边的像素位置
- {
- areaBottom = y;
- }
- //记忆当前像素的比较结果的亮度
- briaryret[briaryidx] = diffbri;
- }
- else //没有差异,设置结果里的当前像素为 相同颜色
- {
- if (fillsamecolor)
- {
- curpixdiff[] = sameB;
- curpixdiff[] = sameG;
- curpixdiff[] = sameR;
- }
- ++samepixcnt;
- //记忆当前像素的比较结果的亮度
- briaryret[briaryidx] = samebri;
- }
- // 比较结果的亮度数组下标
- ++briaryidx;
- //像素是否不同的标志
- compareret.PixIsDifferent[y * width + x] = curpixIsdiff;
- curpix1 += ;
- curpix2 += ;
- curpixdiff += ;
- }
- curpix1 += data1.Stride - width * ;
- curpix2 += data1.Stride - width * ;
- curpixdiff += datadiff.Stride - width * ;
- }
- }
- image1.UnlockBits(data1);
- image2.UnlockBits(data2);
- imagediff.UnlockBits(datadiff);
- compareret.RateDifferent = diffpixcnt / (double)allpixcnt;
- compareret.RateSame = samepixcnt / (double)allpixcnt;
- compareret.CompareResultImage = imagediff;
- compareret.BrightnessDiff = briDiff;
- compareret.BrightnessBytesImage1 = briary1;
- compareret.BrightnessBytesImage2 = briary2;
- compareret.BrightnessBytesResult = briaryret;
- //保存区域范围
- //compareret.DiffAreaTop = areaTop;
- //compareret.DiffAreaLeft = areaLeft;
- //compareret.DiffAreaRight = areaRight;
- //compareret.DiffAreaBottom = areaBottom;
- //compareret.CalculateAreaRate();
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("CompareImage error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 2张图片亮度值相减,得到新图片以及亮度值
- /// </summary>
- /// <param name="image1"></param>
- /// <param name="image2"></param>
- /// <param name="retimage"></param>
- /// <param name="brightnessary"></param>
- /// <returns></returns>
- public static Boolean SubtractImageBrightness(Bitmap image1, Bitmap image2,
- ref Bitmap imagediff, ref Byte[] brightnessary)
- {
- if (image1 == null || image2 == null)
- {
- return false;
- }
- Boolean bl = ResizeImageToSame(ref image1, ref image2);
- if (!bl)
- {
- return false;
- }
- int width = image1.Width;
- int height = image1.Height;
- long allpixcnt = height * width;//所有像素点数量
- brightnessary = new Byte[allpixcnt];
- imagediff = new Bitmap(image1);
- Int32 pixidx = ;//当前像素下标
- byte bri1 = ;
- byte bri2 = ;
- BitmapData data1 = null;
- BitmapData data2 = null;
- BitmapData datadiff = null;
- //每行末尾还有这么多的冗余字节
- Int32 rowredundancy = ;
- try
- {
- data1 = image1.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- data2 = image2.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- datadiff = imagediff.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- rowredundancy = datadiff.Stride - width * ;//每行末尾还有这么多的冗余字节
- Byte bridiff = ;
- unsafe
- {
- byte* curpix1 = (byte*)data1.Scan0.ToPointer();
- byte* curpix2 = (byte*)data2.Scan0.ToPointer();
- byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- bri1 = (byte)((float)(curpix1[] + curpix1[] + curpix1[]) / 3.0f);
- bri2 = (byte)((float)(curpix2[] + curpix2[] + curpix2[]) / 3.0f);
- bridiff = (bri1 > bri2) ? (Byte)(bri1 - bri2) : (Byte)(bri2 - bri1); //计算当前像素点的亮度值
- brightnessary[pixidx] = bridiff;//保存亮度值
- ++pixidx;
- cmpretpix[] = bridiff;//把亮度值设置到结果图像里
- cmpretpix[] = bridiff;
- cmpretpix[] = bridiff;
- curpix1 += ;
- curpix2 += ;
- cmpretpix += ;
- }
- curpix1 += rowredundancy;
- curpix2 += rowredundancy;
- cmpretpix += rowredundancy;
- }
- }
- image1.UnlockBits(data1);
- image2.UnlockBits(data2);
- imagediff.UnlockBits(datadiff);
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("CompareImage error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 根据2个图片的亮度值,比较图片的差异部分,并对比较结果的图片执行去噪点处理
- /// </summary>
- /// <param name="image1"></param>
- /// <param name="image2"></param>
- /// <param name="bridiff">亮度容差</param>
- /// <param name="noisypointsize">噪点边长</param>
- /// <param name="imagediff">比较结果的图片</param>
- /// <param name="diffary">每个像素是否相同</param>
- /// <returns></returns>
- public static Boolean CompareImageByBrightness(Bitmap image1, Bitmap image2,
- Int32 briDiff, Int32 noisypointsize,
- ref Bitmap imagediff, ref Boolean[] diffary)
- {
- if (image1 == null || image2 == null)
- {
- return false;
- }
- Boolean bl = ResizeImageToSame(ref image1, ref image2);
- if (!bl)
- {
- return false;
- }
- if (briDiff < || briDiff > )
- {
- return false;
- }
- if (noisypointsize < || noisypointsize * > image1.Height)
- {
- return false;
- }
- int width = image1.Width;
- int height = image1.Height;
- long allpixcnt = height * width;//所有像素点数量
- imagediff = new Bitmap(image1);
- //每个像素是否相同.1相同,0不同
- diffary = new Boolean[width * height];
- Int32 pixidx = ;//当前像素下标
- byte bri1 = ;
- byte bri2 = ;
- BitmapData data1 = null;
- BitmapData data2 = null;
- BitmapData datadiff = null;
- //每行末尾还有这么多的冗余字节
- Int32 rowredundancy = ;
- try
- {
- data1 = image1.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- data2 = image2.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- datadiff = imagediff.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- rowredundancy = datadiff.Stride - width * ;//每行末尾还有这么多的冗余字节
- unsafe
- {
- byte* curpix1 = (byte*)data1.Scan0.ToPointer();
- byte* curpix2 = (byte*)data2.Scan0.ToPointer();
- byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- bri1 = (byte)((float)(curpix1[] + curpix1[] + curpix1[]) / 3.0f);
- bri2 = (byte)((float)(curpix2[] + curpix2[] + curpix2[]) / 3.0f);
- //比较2个像素亮度值之差,如果有差异,设置图像1里的当前像素为 不同颜色
- if (bri1 >= bri2 + briDiff ||
- bri2 >= bri1 + briDiff)
- {
- diffary[pixidx] = true;
- cmpretpix[] = Const_WhiteBrightness;
- cmpretpix[] = Const_WhiteBrightness;
- cmpretpix[] = Const_WhiteBrightness;
- }
- else
- {
- diffary[pixidx] = false;
- cmpretpix[] = Const_BlackBrightness;
- cmpretpix[] = Const_BlackBrightness;
- cmpretpix[] = Const_BlackBrightness;
- }
- ++pixidx;
- curpix1 += ;
- curpix2 += ;
- cmpretpix += ;
- }
- curpix1 += rowredundancy;
- curpix2 += rowredundancy;
- cmpretpix += rowredundancy;
- }
- }
- image1.UnlockBits(data1);
- image2.UnlockBits(data2);
- imagediff.UnlockBits(datadiff);
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("CompareImage error:" + ex.Message);
- bl = false;
- }
- //现在对图像执行去噪点处理
- RemoveNoisypoint(noisypointsize, ref imagediff);
- //获取去除噪点后各像素亮度
- Byte pixbri = ;//当前像素亮度
- pixidx = ;
- try
- {
- datadiff = imagediff.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- pixbri = (byte)((float)(cmpretpix[] + cmpretpix[] + cmpretpix[]) / 3.0f);
- //去除噪点后,已经变得非黑即白.如果是黑色,表示相同,白色,表示不同
- diffary[pixidx] = (pixbri > briDiff);
- ++pixidx;
- cmpretpix += ;
- }
- cmpretpix += rowredundancy;
- }
- }
- imagediff.UnlockBits(datadiff);
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("CompareImage error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// 根据2个图片的亮度值,比较图片的差异部分
- /// </summary>
- /// <param name="compareparam"></param>
- /// <param name="compareret"></param>
- /// <returns></returns>
- public static Boolean CompareImageByBrightness(ImageCompareParameter compareparam,
- ref ImageCompareResult compareret)
- {
- Bitmap image1 = compareparam.Image1;
- Bitmap image2 = compareparam.Image2;
- Byte[] imagebri1 = compareparam.BrightnessBytesImage1;
- Byte[] imagebri2 = compareparam.BrightnessBytesImage2;
- Int32 briDiff = compareparam.BrightnessDiff;
- Color diffColor = compareparam.DifferentAreaFillColor;
- Color samecolor = compareparam.SameAreaFillColor;
- //是否需要填充相同或不同部分的像素的颜色
- Boolean filldiffcolor = (diffColor != Color.Transparent);
- Boolean fillsamecolor = (samecolor != Color.Transparent);
- Boolean bl = false;
- Bitmap imagediff = new Bitmap(image1);
- //不同区域的左上下右位置
- Int32 areaLeft = imagediff.Width;
- Int32 areaTop = imagediff.Height;
- Int32 areaRight = -;
- Int32 areaBottom = -;
- int width = image1.Width;
- int height = image1.Height;
- long allpixcnt = height * width;//所有像素点数量
- long diffpixcnt = ;//不同像素点数量
- long samepixcnt = ;//相同像素点数量
- if (imagebri1 == null || imagebri2 == null ||
- imagebri2.Length != imagebri2.Length ||
- imagebri2.Length != allpixcnt)
- {
- return false;
- }
- //3张图片的各像素亮度数组
- Int32 briaryidx = ;
- Byte[] briaryret = new Byte[allpixcnt];
- Byte diffB = diffColor.B;
- Byte diffG = diffColor.G;
- Byte diffR = diffColor.R;
- Byte sameB = samecolor.B;
- Byte sameG = samecolor.G;
- Byte sameR = samecolor.R;
- Byte samebri = ;
- Byte diffbri = ;
- GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);
- GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);
- Int32 currowfirstx = ;//当前行的首个像素的下标
- try
- {
- BitmapData data1 = image1.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- BitmapData data2 = image2.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- BitmapData datadiff = imagediff.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- byte bri1 = ;
- byte bri2 = ;
- //每个像素是否相同.1相同,0不同
- compareret.PixIsDifferent = new Boolean[width * height];
- //当前像素是否不同
- Boolean curpixIsdiff = false;
- unsafe
- {
- byte* curpix1 = (byte*)data1.Scan0.ToPointer();
- byte* curpix2 = (byte*)data2.Scan0.ToPointer();
- byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- currowfirstx = y * width;
- for (int x = ; x < width; x++)
- {
- bri1 = imagebri1[currowfirstx + x];
- bri2 = imagebri2[currowfirstx + x];
- //以1作为基准,比较1和2之间的差距,如果超过阀值,认为当前像素有差异
- //否则认为当前像素没有差异
- curpixIsdiff = false;
- if (bri1 >= bri2 + briDiff ||
- bri2 >= bri1 + briDiff)
- {
- curpixIsdiff = true;
- }
- if (curpixIsdiff) //如果有差异,设置图像1里的当前像素为 不同颜色
- {
- if (filldiffcolor)
- {
- cmpretpix[] = diffB;
- cmpretpix[] = diffG;
- cmpretpix[] = diffR;
- }
- ++diffpixcnt;
- if (x < areaLeft) //记忆最左边的像素位置
- {
- areaLeft = x;
- }
- if (x > areaRight) //记忆最右边的像素位置
- {
- areaRight = x;
- }
- if (y < areaTop) //记忆最上边的像素位置
- {
- areaTop = y;
- }
- if (y > areaBottom) //记忆最下边的像素位置
- {
- areaBottom = y;
- }
- //记忆当前像素的比较结果的亮度
- briaryret[briaryidx] = diffbri;
- }
- else //没有差异,设置结果里的当前像素为 相同颜色
- {
- if (fillsamecolor)
- {
- cmpretpix[] = sameB;
- cmpretpix[] = sameG;
- cmpretpix[] = sameR;
- }
- ++samepixcnt;
- //记忆当前像素的比较结果的亮度
- briaryret[briaryidx] = samebri;
- }
- // 比较结果的亮度数组下标
- ++briaryidx;
- //像素是否不同的标志
- compareret.PixIsDifferent[currowfirstx + x] = curpixIsdiff;
- curpix1 += ;
- curpix2 += ;
- cmpretpix += ;
- }
- curpix1 += data1.Stride - width * ;
- curpix2 += data1.Stride - width * ;
- cmpretpix += datadiff.Stride - width * ;
- }
- }
- image1.UnlockBits(data1);
- image2.UnlockBits(data2);
- imagediff.UnlockBits(datadiff);
- compareret.RateDifferent = diffpixcnt / (double)allpixcnt;
- compareret.RateSame = samepixcnt / (double)allpixcnt;
- compareret.CompareResultImage = imagediff;
- compareret.BrightnessDiff = briDiff;
- compareret.BrightnessBytesResult = briaryret;
- bl = true;
- }
- catch (Exception ex)
- {
- Console.WriteLine("CompareImage error:" + ex.Message);
- bl = false;
- }
- return bl;
- }
- /// <summary>
- /// 获取一个区域的实际坐标
- /// </summary>
- /// <param name="area"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="x1"></param>
- /// <param name="y1"></param>
- /// <param name="x2"></param>
- /// <param name="y2"></param>
- public static void GetAreaPositionInImage(ImageAreaInfo area,
- Int32 width, Int32 height,
- ref Int32 x1, ref Int32 y1, ref Int32 x2, ref Int32 y2)
- {
- if (area.PositionType == ePositionType.ByPix)
- {
- x1 = (Int32)area.X1;
- y1 = (Int32)area.Y1;
- x2 = (Int32)area.X2;
- y2 = (Int32)area.Y2;
- }
- else
- {
- x1 = (Int32)(area.X1 * (double)width);
- y1 = (Int32)(area.Y1 * (double)height);
- x2 = (Int32)(area.X2 * (double)width);
- y2 = (Int32)(area.Y2 * (double)height);
- }
- }
- /// <summary>
- /// 检查指定区域的图像是否与方案里的指定值一样(都是相同或者不同)
- /// </summary>
- /// <param name="briDiffary">每个元素对应2张图片的每个像素亮度相同还是不同.true不同,false相同</param>
- /// <param name="area"></param>
- /// <returns></returns>
- public static Boolean ValidateImageArea(Boolean[] briDiffary, ImageAreaInfo area, Int32 width, Int32 height)
- {
- if (briDiffary == null || briDiffary.Length < || area == null ||
- width < || height < || width * height != briDiffary.Length)
- {
- return false;
- }
- Int32 x1 = ;
- Int32 x2 = ;
- Int32 y1 = ;
- Int32 y2 = ;
- //获取该区域在图像里的实际坐标范围
- GetAreaPositionInImage(area, width, height,
- ref x1, ref y1, ref x2, ref y2);
- //获取该区域里的像素匹配类型
- eAreaDifferentType difftype = eAreaDifferentType.Partial;
- Boolean bl = GetImageAreaDifferentType(briDiffary, width, height,
- x1, y1, x2, y2, ref difftype);
- if (!bl)
- {
- return false;
- }
- //如果是期待所有像素都是相同,要求必须每个像素都相同.任何一个不同,就认为失败
- if (area.ExpectDispMode == eDrawType.ExpectHide &&
- difftype != eAreaDifferentType.AllSame)
- {
- return false;
- }
- //如果是期待像素不同,只要有1个像素不同就可以.所有像素都相同,认为失败
- if (area.ExpectDispMode == eDrawType.ExpectShow &&
- difftype == eAreaDifferentType.AllSame)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 检查指定区域的图像是否与方案里的指定值一样(都是相同或者不同)
- /// </summary>
- /// <param name="pixDiffary"></param>
- /// <param name="area"></param>
- /// <returns></returns>
- public static Boolean ValidateImageArea(Byte[] briDiffary, ImageAreaInfo area, Int32 width, Int32 height)
- {
- Boolean[] blary = new Boolean[briDiffary.Length];
- for (Int32 idx = ; idx < briDiffary.Length; ++idx)
- {
- blary[idx] = (briDiffary[idx] > );
- }
- Boolean bl = ValidateImageArea(blary, area, width, height);
- return bl;
- }
- /// <summary>
- /// 检查图片的比较结果里,某个区域是否与期待的一致
- /// </summary>
- /// <param name="compareret"></param>
- /// <param name="area"></param>
- /// <returns>true-与期待一致;false-不一致</returns>
- public static Boolean ValidateImageArea(ImageCompareResult compareret, ImageAreaInfo area)
- {
- Boolean[] pixDiffary = compareret.PixIsDifferent;
- Bitmap tmp = new Bitmap(compareret.CompareResultImage);
- Int32 width = tmp.Width;
- Int32 height = tmp.Height;
- Boolean bl = ValidateImageArea(compareret.PixIsDifferent, area, width, height);
- return bl;
- }
- /// <summary>
- /// 获取1个 比较结果里,指定的区域范围,是全都相同,还是不同
- /// 只有所有像素都是相同,才认为是整个区域相同
- /// 如果有1个像素不同,则认为整个区域不同
- /// </summary>
- /// <param name="pixDiffary"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="startX"></param>
- /// <param name="startY"></param>
- /// <param name="endX"></param>
- /// <param name="endY"></param>
- /// <returns> </returns>
- public static Boolean GetImageAreaDifferentType(Boolean[] pixDiffary, Int32 width, Int32 height,
- Int32 x1, Int32 y1, Int32 x2, Int32 y2, ref eAreaDifferentType difftype)
- {
- Int32 areawidth = x2 - x1;
- Int32 areaheight = y2 - y1;
- if (pixDiffary == null || width < || height < ||
- areawidth < || areaheight < ||
- width < areawidth || height < areaheight ||
- pixDiffary.Length < width * height)
- {
- return false;
- }
- Boolean allissame = false; //假设所有像素相同
- Boolean allisdiff = false; //假设所有像素不同
- Int32 currowFirstPix = ;
- for (Int32 y = y1; y <= y2; ++y)
- {
- currowFirstPix = y * width;
- for (Int32 x = x1; x <= x2; ++x)
- {
- if (pixDiffary[currowFirstPix + x]) //当前像素点不同
- {
- allisdiff = true;
- }
- else//当前像素相同
- {
- allissame = true;
- }
- //如果已经有部分相同部分不同,退出
- if (allisdiff && allissame)
- {
- difftype = eAreaDifferentType.Partial;
- return true;
- }
- }
- }
- //现在,所有像素都相同,或都不同
- if (allisdiff)
- {
- difftype = eAreaDifferentType.AllDifferent;
- }
- else
- {
- difftype = eAreaDifferentType.AllSame;
- }
- return true;
- }
- /// <summary>
- /// 根据亮度容差,把图片转换为非黑即白的图片
- /// </summary>
- /// <param name="briimg"></param>
- /// <param name="brigate"></param>
- /// <returns></returns>
- public static Boolean GetBlackWhiteImage(Bitmap briimg, Byte[] briDiffary, Int32 brigate, ref Bitmap blackwhiteimage)
- {
- if (briimg == null)
- {
- return false;
- }
- int width = briimg.Width;
- int height = briimg.Height;
- long allpixcnt = height * width;//所有像素点数量
- if (briDiffary == null || briDiffary.Length != allpixcnt)
- {
- return false;
- }
- blackwhiteimage = new Bitmap(briimg);
- Int32 pixidx = ;//当前像素下标
- BitmapData datasrc = null;
- BitmapData dataret = null;
- //每行末尾还有这么多的冗余字节
- Int32 rowredundancy = ;
- Byte curpixBri = ;//当前的亮度
- try
- {
- datasrc = briimg.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- dataret = blackwhiteimage.LockBits(new Rectangle(, , width, height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- rowredundancy = datasrc.Stride - width * ;//每行末尾还有这么多的冗余字节
- unsafe
- {
- byte* pixret = (byte*)dataret.Scan0.ToPointer();
- for (int y = ; y < height; y++)
- {
- for (int x = ; x < width; x++)
- {
- //亮度差值大于门限的,认为是不同部分,用白色填充
- curpixBri = (briDiffary[pixidx] > brigate) ? Const_BrightnessWhite : Const_BrightnessBlack;
- pixret[] = curpixBri;//把亮度值设置到结果图像里
- pixret[] = curpixBri;
- pixret[] = curpixBri;
- ++pixidx;
- pixret += ;
- }
- pixret += rowredundancy;
- }
- }
- briimg.UnlockBits(datasrc);
- blackwhiteimage.UnlockBits(dataret);
- }
- catch (Exception ex)
- {
- Console.WriteLine("GetBlackWhiteImage error:" + ex.Message);
- return false;
- }
- return true;
- }
- #endregion
- #region 内部实现
- /// <summary>
- /// 比较2个数值之间的差是否大于指定值
- /// </summary>
- /// <param name="val1"></param>
- /// <param name="val2"></param>
- /// <param name="diff"></param>
- /// <returns>超过指定值返回true;否则返回false</returns>
- private static Boolean CheckDiffOver(Int32 val1, Int32 val2, Int32 diff)
- {
- if (diff < )
- {
- return false;
- }
- if (val1 > val2 && val1 > val2 + diff)
- {
- return true;
- }
- if (val2 > val1 && val2 > val1 + diff)
- {
- return true;
- }
- return false;
- }
- #endregion
- }
- }
【转】C#使用ESC指令控制POS打印机打印小票的更多相关文章
- C#使用ESC指令控制POS打印机打印小票
1.前言 C#打印小票可以与普通打印机一样,调用PrintDocument实现.也可以发送标注你的ESC指令实现.由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的po ...
- android 控制POS机图文打印(二)
上一篇文章结束了ESC/POS的指令集,没看过的可以去看一下,可以当作工具文档来使用的 android 控制POS机图文打印(一) 这一篇正式介绍如何使用POS机来打印图文信息. 首先介绍一下,ESC ...
- Java 实现 POS 打印机无驱打印
来源:https://www.ibm.com/developerworks/cn/java/j-lo-pos/index.html 行业需求 我们是一家专业做酒店餐饮软件的公司,餐饮软件一个重要的功能 ...
- Java实现POS打印机自定义无驱打印
Java实现POS打印机自定义无驱打印 热敏打印机使用越来越广泛,而安装驱动相当复杂,万幸的是,几乎所有的热敏打印机都支持ESC/P指令,参考网络上一些资料后,在此整理了一份自定义打印的方案 • 打印 ...
- Java使用POS打印机(无驱)
使用原因:应项目要求,需要使用打印机,但是如果使用Windows驱动来实现打印,在某些条件下会发生网络堵塞等,而且没有提示,所以为了确保信息的完整,避免数据丢失.我们使用无驱打印(直接写端口的方法), ...
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)【转】
原文地址:http://blog.csdn.net/ldljlq/article/details/7338772 在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇 ...
- PHP控制连接打印机
一.需求 使用PHP控制连接打印机 现场实时连续打印动态数据 二.配置 php运行环境正确安装(Apache|Nginx + PHP) 下载与php版本对应的php_printer.dll扩展 扩展文 ...
- C# 网络打印机ESC指令打印小票
public void SendSocketMsg(String ip, int port, int times, byte[] data) { try { byte[] mData; ) { mDa ...
- Atitit.收银系统pos 以及打印功能的行业标准
Atitit.收银系统pos 以及打印功能的行业标准 1. ESC指令序列 Escape指令序列不同于ESC/POS指令 1 2. 打印标准OPOS POSPrinter 与 CashDrawer 驱 ...
随机推荐
- 网络编程学习笔记:linux下的socket编程
socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...
- ssh 使用密钥与登录进行远程cp
scp -P 50000 -i abc.pem ubuntu@10.223.191.105://srv/log/webserver/main/nginx.access.2015-08-07.log ...
- laravel 在windows中使用一键安装包步骤
安装 PHP 注意一:Laravel 5.0 开始对 PHP 版本的要求是 >=5.4,Laravel 5.1 要求 PHP 版本 >=5.5.9,所以,建议大家尽量安装 5.5.x 的最 ...
- l段子
段子简介 L段子起源.L段子是开发者根据市场调查, 用户可在等候列车,飞机,或在公交车上无 聊之余使用本应用.打发无聊的时间,分为段 子,图片,活动和个人中心,用户可根据自己 喜好进入不同的区域.段子 ...
- swift:谈谈swift几种常见属性的区别
一.前奏 Swift作为一门新语言,经过几年的发展,逐渐趋于完善,目前已经更新到3.0版本,它汇集许多其他语言的特点,例如JS.Paython.C++等,完全区别于OC.个人感觉它没有完全的OOP和O ...
- 使用WKWebView遇到的坑
苹果从iOS8开始推出了WKWebView,大有替换UIWebView的意思(尽管Xcode中还没给UIWebView标记过期版本),所以决定将项目进行适配,iOS8及以上版本,改用WKWebView ...
- 使用git版本控制器C#工程,git托管到GitHub和visual studio on line
类比TFS, 托管到了VS online,为私有.GitHub上托管的代码为开源. 新建工程选择版本控制器"Git" VS online: 本地: GitHub,下载github ...
- tomcat 格式化输出到kafka
cat /data/tomcat/conf/server.xml <Valve className="org.apache.catalina.valves.AccessLogValve ...
- js 将json字符串转换为json对象的方法解析
推荐: var obj = eval('(' + str + ')'); var last=JSON.stringify(obj); //将JSON对象转化为string字符 例如: JSON字符串: ...
- Android四大核心组件之ContentProvider
实验内容 学习ContextProvider用法 编码实现简单ContextProvider功能 实验要求 通过简单代码了解ContextProvider功能和用法 实验步骤 ContextProvi ...