1.前言

C#打印小票可以与普通打印机一样,调用PrintDocument实现。也可以发送标注你的ESC指令实现。由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的pos打印机,并且无法发送控制指令实现pos打印机的切纸、走纸等动作。因此个人建议使用ESC指令进行打印会更通用。

本类需要调用 ImageProcessor.cs

2.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 = 0,

Middle = 1,

Right = 2

}

#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 = "01";

private const String Const_Bold_NO = "00";

//设置对齐方式

private const string Const_SetAlign = "1B 61 ";

private const String Const_Align_Left = "30";

private const String Const_Align_Middle = "31";

private const String Const_Align_Right = "32";

//设置字体大小,与 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 = 8;

/// <summary>

/// 最大走纸距离

/// </summary>

public const Int32 Const_MaxFeedLength = 5000;

/// <summary>

/// 最大高宽

/// </summary>

public const Int32 Const_MaxImageLength = 480;

/// <summary>

/// 每次通信最多打印的行数

/// </summary>

public const Int32 Const_OncePrintRowCount = 24;

public const Int32 Const_BrightnessGate = 100;

/// <summary>

/// 无效句柄

/// </summary>

public const Int32 Const_InvalidHandle = -1;

#endregion

#region 私有成员

/// <summary>

/// 打印机句柄

/// </summary>

private int m_Handle = -1;

/// <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 < 2)

{

return false;

}

int writelen = 0;

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 < 4)

{

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 = 0;

Int32 newheight = 0;

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 != 0)

{

height = height + Const_OncePrintRowCount - height % Const_OncePrintRowCount;

}

width = img.Width;//如果图像宽度不是8的整数倍,设置为8的整数倍

if (width % 8 != 0)

{

width = width + 8 - width % 8;

}

Int32 bytelen = height * width / 8;//每个像素对应1个比特位,因此总字节数=像素位数/8

allbitary = new Byte[bytelen];

Int32 byteidxInCol = 0;//当前列里首个像素,在目标字节数组里的下标

Int32 byteidx = 0;//当前像素在目标数组里的字节下标

Int32 bitidx = 0;//当前像素在目标数组里当前字节里的比特位下标

Int32 pixidxInCol = 0;//当前像素在当前列里的第几个位置

Int32 pixidx = 0;//当前像素在原始图片里的下标

Int32 rowidx = 0; //当前 处理的像素点所在行,不能超过 图像高度

Int32 curprocrows = 0;//当前需要处理的行数量

while (rowidx < height)

{

//按照纵向次序,把当前列的24个数据,转换为3个字节

for (Int32 colidx = 0; colidx < img.Width; ++colidx)

{

//如果当前还剩余超过24行没处理,处理24行

if (rowidx + Const_OncePrintRowCount <= img.Height)

{

curprocrows = Const_OncePrintRowCount;

}

else

{

//已经不足24行,只处理剩余行数

curprocrows = img.Height - rowidx;

}

pixidxInCol = 0; //本列里从像素0开始处理

for (Int32 y = rowidx; y < rowidx + curprocrows; ++y)

{

//原始图片里像素位置

pixidx = y * img.Width + colidx;

//获取当前像素的亮度值.如果当前像素是黑点,需要把数组里的对应比特位设置为1

if (briary[pixidx])

{

bitidx = 7 - pixidxInCol % 8;//最高比特位对应首个像素.最低比特位对应末个像素

byteidx = byteidxInCol + pixidxInCol / 8; //由于最后一段可能不足24行,因此不能使用byteidx++

DataFormatProcessor.SetBitValue(bitidx, true, ref allbitary[byteidx]);

}

pixidxInCol++;

}

byteidxInCol += 3;//每列固定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 < 1)

{

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 != 0);

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, 1, 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 = -1;

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 < 1)

{

content =  "  ";

}

if (content[content.Length - 1] != (char)0x0D &&

content[content.Length - 1] != (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(2, 2) + hexstr.Substring(0, 2);

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 = 0;

Int32 height = 0;

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 / 8;

//检查是否尺寸符合要求

if (width > Const_MaxImageLength || height > Const_MaxFeedLength ||

width < 1 || height < 1 ||

imgbitarray == null)

{

return false;

}

//每次获取24行的数据进行发送,这24行的字节数

Int32 blockbytes = width * Const_OncePrintRowCount / 8;

if (blockbytes < 1)

{

return false;

}

Boolean bl = false;

//一共需要发送的块数量

Int32 blocks = imgbitarray.Length / blockbytes;

//每次发送的数据字节数 = 1B 2A 21 2字节长度 + 数据内容

Byte[] cmdbytes = new Byte[5 + blockbytes];

//指令

Array.Copy(Const_SetImageCommand, cmdbytes, 3);

//数据长度,即 每行的点数

DataFormatProcessor.Int16ToBytes(width, ref cmdbytes, 3);

//数据内容

for (Int32 blockidx = 0; blockidx < blocks; ++blockidx)

{

Array.Copy(imgbitarray, blockidx * blockbytes, cmdbytes, 5, blockbytes);

//发送当前指令

bl = SendCommand(cmdbytes);

if (!bl) return false;

//休眠20毫秒

Thread.Sleep(20);

//发送 打印指令

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 < 1)

length = 1;

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 < 1)

length = 1;

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 < 1)

{

sizerate = 1;

}

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

}

}

3.图像处理 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 = 0,

Gif = 1,

Icon = 2,

Jpeg = 3,

Png = 4,

}

/// <summary>

/// 转为灰度图像的方式

/// </summary>

public enum eGrayMode

{

/// <summary>

/// 算数平均

/// </summary>

ArithmeticAverage = 0,

/// <summary>

/// 加权平均

/// </summary>

WeightedAverage = 1,

}

/// <summary>

/// 比较2个图片的指定区域范围,像素的相同类型

/// </summary>

public enum eAreaDifferentType

{

/// <summary>

/// 所有像素都相同

/// </summary>

AllSame = 0,

/// <summary>

/// 所有像素都不同

/// </summary>

AllDifferent = 1,

/// <summary>

/// 部分相同部分不同

/// </summary>

Partial = 2,

}

/// <summary>

/// 图片文件处理

/// </summary>

public class ImageProcessor

{

#region 常量定义

public const Byte Const_BrightnessWhite = 255;

public const Byte Const_BrightnessBlack = 0;

/// <summary>

/// 比较结果的图片里,亮度相同部分的填充颜色

/// </summary>

public static Color Const_SameBrightnessColor = Color.Black;

/// <summary>

/// 比较结果的图片里,亮度相同部分的填充颜色

/// </summary>

public static Color Const_DifferentBrightnessColor = Color.White;

public const Byte Const_BlackBrightness = 0;

public const Byte Const_WhiteBrightness = 255;

public const Int32 Const_MaxBrightness = 255;

public const Int32 Const_MinBrightness = -255;

/// <summary>

/// 亮度的中间值

/// </summary>

public const Int32 Const_MiddleBrightness = 128;

#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,

0, 0, ctrl.Size);

g.DrawImage(ret, 0, 0);

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 > 0);

}

/// <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 = 0;

try

{

BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* curpix = (byte*)srcData.Scan0.ToPointer();

if (mode == eGrayMode.ArithmeticAverage)// 算数平均

{

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

newColor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);

curpix[0] = newColor;

curpix[1] = newColor;

curpix[2] = newColor;

curpix += 3;

}

curpix += srcData.Stride - width * 3;

}

}

else

{

// 加权平均

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

newColor = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);

curpix[0] = newColor;

curpix[1] = newColor;

curpix[2] = newColor;

curpix += 3;

}

curpix += srcData.Stride - width * 3;

}

}

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 < 1 || height < 1)

{

return false;

}

brightnessary = new Byte[width * height];

Boolean bl = false;

Int32 rowredundancy = 0;//每一行像素,对应的数组长度 与 实际像素点数的差值

Int32 pixidx = 0;//像素下标

try

{

BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

rowredundancy = srcData.Stride - width * 3;//每行末尾还有这么多的冗余字节

unsafe

{

byte* curpix = (byte*)srcData.Scan0.ToPointer();

if (mode == eGrayMode.ArithmeticAverage)// 算数平均

{

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

brightnessary[pixidx] = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);

++pixidx;

curpix += 3;

}

curpix += rowredundancy;

}

}

else

{

// 加权平均

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

brightnessary[pixidx] = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);

++pixidx;

curpix += 3;

}

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 = 0;

Int32 bytesidx = 0;

Boolean bl = false;

try

{

BitmapData srcData = graybitmap.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* curpix = (byte*)srcData.Scan0.ToPointer();

if (mode == eGrayMode.ArithmeticAverage)// 算数平均

{

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

newColor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);

brightnessbytes[bytesidx] = newColor;

++bytesidx;

curpix[0] = newColor;

curpix[1] = newColor;

curpix[2] = newColor;

curpix += 3;

}

curpix += srcData.Stride - width * 3;

}

}

else

{

// 加权平均

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

newColor = (byte)((float)curpix[0] * 0.114f + (float)curpix[1] * 0.587f + (float)curpix[2] * 0.299f);

brightnessbytes[bytesidx] = newColor;

++bytesidx;

curpix[0] = newColor;

curpix[1] = newColor;

curpix[2] = newColor;

curpix += 3;

}

curpix += srcData.Stride - width * 3;

}

}

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 = 0;

Int32 pixidx = 0;

Boolean bl = false;

try

{

BitmapData srcData = bitmap.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* curpix = (byte*)srcData.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

curcolor = (byte)((float)(curpix[0] + curpix[1] + curpix[2]) / 3.0f);

if (trueAsblack)//true为黑点

{

bitary[pixidx] = (curcolor < brightnessGate);

}

else

{

//true为白点

bitary[pixidx] = (curcolor > brightnessGate);

}

++pixidx;

curpix += 3;

}

curpix += srcData.Stride - width * 3;

}

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 < 4)

{

return false;

}

boolary = new Boolean[bridiffary.Length];

for (Int32 idx = 0; 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(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* curpix = (byte*)data.Scan0.ToPointer();

Int32 curcolor = 0;

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

curcolor = curpix[0] + brightnessOffset;

CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);

curpix[0] = (byte)curcolor;

curcolor = curpix[1] + brightnessOffset;

CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);

curpix[1] = (byte)curcolor;

curcolor = curpix[2] + brightnessOffset;

CommonCompute.SetInt32Range(ref curcolor, 0, Const_MaxBrightness);

curpix[2] = (byte)curcolor;

curpix += 3;

}

curpix += data.Stride - width * 3;

}

}

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, 0, 100);

Int32 curcolor = 0;

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 = 0;

if (contrast == 50)

{

rate = 1;

}

else if (contrast < 50)

{

rate = contrast / 50.0;//小于50的,对比度比率必须是纯小数,0-1 之间

}

else

{

rate = 1 + Const_MiddleBrightness * ((contrast - 50.0) / 50.0);//大于50的,比率必须是1到128之间的值

}

try

{

BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* curpix = (byte*)data.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

for (int i = 0; i < 3; i++) //R,G,B 3个通道

{

//对于 刚好亮度等于中间值的点,需要把亮度调高或调低1

//否则将无法实现对该点 提高对比度

if (curpix[i] == Const_MiddleBrightness)

{

curpix[i] = (byte)(curpix[i] + 1);

}

//调整该像素对比度

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 * 3;

}

}

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 + 2;

int h = srcbitmap.Height + 2;

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, 1, 1);

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, 0, 0);

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(0, 0, srcbitmap.Width, srcbitmap.Height), 0, 0, 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(0, 0, newW, newH),

new Rectangle(0, 0, 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 < 1 ||

noisypointsize * 2 >= bitmap.Width || noisypointsize * 2 >= 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 < 0 || y < 0 || width < 1 || height < 1 ||

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(0, 0, 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 < 0 || x >= bitmap.Width ||

y < 0 || 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 < 1 || height < 1 ||

x < 0 || x >= width ||

y < 0 || 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 < 1 || height < 1 ||

x < 0 || x >= width ||

y < 0 || 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 < 0 || x >= bitmap.Width ||

y < 0 || 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 < 1 || brightness2.Length < 1 ||

brightness1.Length != brightness2.Length)

{

return false;

}

Int32 arylen = brightness1.Length;

diffPixArray = new Boolean[brightness1.Length];

Byte bri1 = 0;

Byte bri2 = 0;

for (Int32 byteidx = 0; 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 == 0 || image1.Height == 0 ||

image2.Width == 0 || image2.Height == 0)

{

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 = -1;

Int32 areaBottom = -1;

int width = image1.Width;

int height = image1.Height;

long allpixcnt = height * width;//所有像素点数量

long diffpixcnt = 0;//不同像素点数量

long samepixcnt = 0;//相同像素点数量

//3张图片的各像素亮度数组

Int32 briaryidx = 0;

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 = 0;

Byte diffbri = 0;

GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);

GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);

try

{

BitmapData data1 = image1.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData data2 = image2.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

byte bri1 = 0;

byte bri2 = 0;

//每个像素是否相同.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 = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

//利用公式计算灰度值(加权平均法)

//按BGR的顺序存储

bri1 = (Byte)(curpix1[0] * 0.114f + curpix1[1] * 0.587f + curpix1[2] * 0.299f);

bri2 = (Byte)(curpix2[0] * 0.114f + curpix2[1] * 0.587f + curpix2[2] * 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[0] = diffB;

curpixdiff[1] = diffG;

curpixdiff[2] = 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[0] = sameB;

curpixdiff[1] = sameG;

curpixdiff[2] = sameR;

}

++samepixcnt;

//记忆当前像素的比较结果的亮度

briaryret[briaryidx] = samebri;

}

// 比较结果的亮度数组下标

++briaryidx;

//像素是否不同的标志

compareret.PixIsDifferent[y * width + x] = curpixIsdiff;

curpix1 += 3;

curpix2 += 3;

curpixdiff += 3;

}

curpix1 += data1.Stride - width * 3;

curpix2 += data1.Stride - width * 3;

curpixdiff += datadiff.Stride - width * 3;

}

}

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 = 0;//当前像素下标

byte bri1 = 0;

byte bri2 = 0;

BitmapData data1 = null;

BitmapData data2 = null;

BitmapData datadiff = null;

//每行末尾还有这么多的冗余字节

Int32 rowredundancy = 0;

try

{

data1 = image1.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

data2 = image2.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

rowredundancy = datadiff.Stride - width * 3;//每行末尾还有这么多的冗余字节

Byte bridiff = 0;

unsafe

{

byte* curpix1 = (byte*)data1.Scan0.ToPointer();

byte* curpix2 = (byte*)data2.Scan0.ToPointer();

byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

bri1 = (byte)((float)(curpix1[0] + curpix1[1] + curpix1[2]) / 3.0f);

bri2 = (byte)((float)(curpix2[0] + curpix2[1] + curpix2[2]) / 3.0f);

bridiff = (bri1 > bri2) ? (Byte)(bri1 - bri2) : (Byte)(bri2 - bri1); //计算当前像素点的亮度值

brightnessary[pixidx] = bridiff;//保存亮度值

++pixidx;

cmpretpix[0] = bridiff;//把亮度值设置到结果图像里

cmpretpix[1] = bridiff;

cmpretpix[2] = bridiff;

curpix1 += 3;

curpix2 += 3;

cmpretpix += 3;

}

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 < 1 || briDiff > 255)

{

return false;

}

if (noisypointsize < 1 || noisypointsize * 2 > 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 = 0;//当前像素下标

byte bri1 = 0;

byte bri2 = 0;

BitmapData data1 = null;

BitmapData data2 = null;

BitmapData datadiff = null;

//每行末尾还有这么多的冗余字节

Int32 rowredundancy = 0;

try

{

data1 = image1.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

data2 = image2.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

rowredundancy = datadiff.Stride - width * 3;//每行末尾还有这么多的冗余字节

unsafe

{

byte* curpix1 = (byte*)data1.Scan0.ToPointer();

byte* curpix2 = (byte*)data2.Scan0.ToPointer();

byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

bri1 = (byte)((float)(curpix1[0] + curpix1[1] + curpix1[2]) / 3.0f);

bri2 = (byte)((float)(curpix2[0] + curpix2[1] + curpix2[2]) / 3.0f);

//比较2个像素亮度值之差,如果有差异,设置图像1里的当前像素为 不同颜色

if (bri1 >= bri2 + briDiff ||

bri2 >= bri1 + briDiff)

{

diffary[pixidx] = true;

cmpretpix[0] = Const_WhiteBrightness;

cmpretpix[1] = Const_WhiteBrightness;

cmpretpix[2] = Const_WhiteBrightness;

}

else

{

diffary[pixidx] = false;

cmpretpix[0] = Const_BlackBrightness;

cmpretpix[1] = Const_BlackBrightness;

cmpretpix[2] = Const_BlackBrightness;

}

++pixidx;

curpix1 += 3;

curpix2 += 3;

cmpretpix += 3;

}

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 = 0;//当前像素亮度

pixidx = 0;

try

{

datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe

{

byte* cmpretpix = (byte*)datadiff.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

pixbri = (byte)((float)(cmpretpix[0] + cmpretpix[1] + cmpretpix[2]) / 3.0f);

//去除噪点后,已经变得非黑即白.如果是黑色,表示相同,白色,表示不同

diffary[pixidx] = (pixbri > briDiff);

++pixidx;

cmpretpix += 3;

}

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 = -1;

Int32 areaBottom = -1;

int width = image1.Width;

int height = image1.Height;

long allpixcnt = height * width;//所有像素点数量

long diffpixcnt = 0;//不同像素点数量

long samepixcnt = 0;//相同像素点数量

if (imagebri1 == null || imagebri2 == null ||

imagebri2.Length != imagebri2.Length ||

imagebri2.Length != allpixcnt)

{

return false;

}

//3张图片的各像素亮度数组

Int32 briaryidx = 0;

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 = 0;

Byte diffbri = 0;

GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref samebri);

GetBrightnessByColor(diffColor, eGrayMode.WeightedAverage, ref diffbri);

Int32 currowfirstx = 0;//当前行的首个像素的下标

try

{

BitmapData data1 = image1.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData data2 = image2.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData datadiff = imagediff.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

byte bri1 = 0;

byte bri2 = 0;

//每个像素是否相同.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 = 0; y < height; y++)

{

currowfirstx = y * width;

for (int x = 0; 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[0] = diffB;

cmpretpix[1] = diffG;

cmpretpix[2] = 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[0] = sameB;

cmpretpix[1] = sameG;

cmpretpix[2] = sameR;

}

++samepixcnt;

//记忆当前像素的比较结果的亮度

briaryret[briaryidx] = samebri;

}

// 比较结果的亮度数组下标

++briaryidx;

//像素是否不同的标志

compareret.PixIsDifferent[currowfirstx + x] = curpixIsdiff;

curpix1 += 3;

curpix2 += 3;

cmpretpix += 3;

}

curpix1 += data1.Stride - width * 3;

curpix2 += data1.Stride - width * 3;

cmpretpix += datadiff.Stride - width * 3;

}

}

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 < 4 || area == null ||

width < 1 || height < 1 || width * height != briDiffary.Length)

{

return false;

}

Int32 x1 = 0;

Int32 x2 = 0;

Int32 y1 = 0;

Int32 y2 = 0;

//获取该区域在图像里的实际坐标范围

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 = 0; idx < briDiffary.Length; ++idx)

{

blary[idx] = (briDiffary[idx] > 0);

}

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 < 1 || height < 1 ||

areawidth < 1 || areaheight < 1 ||

width < areawidth || height < areaheight ||

pixDiffary.Length < width * height)

{

return false;

}

Boolean allissame = false; //假设所有像素相同

Boolean allisdiff = false; //假设所有像素不同

Int32 currowFirstPix = 0;

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 = 0;//当前像素下标

BitmapData datasrc = null;

BitmapData dataret = null;

//每行末尾还有这么多的冗余字节

Int32 rowredundancy = 0;

Byte curpixBri = 0;//当前的亮度

try

{

datasrc = briimg.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

dataret = blackwhiteimage.LockBits(new Rectangle(0, 0, width, height),

ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

rowredundancy = datasrc.Stride - width * 3;//每行末尾还有这么多的冗余字节

unsafe

{

byte* pixret = (byte*)dataret.Scan0.ToPointer();

for (int y = 0; y < height; y++)

{

for (int x = 0; x < width; x++)

{

//亮度差值大于门限的,认为是不同部分,用白色填充

curpixBri = (briDiffary[pixidx] > brigate) ? Const_BrightnessWhite : Const_BrightnessBlack;

pixret[0] = curpixBri;//把亮度值设置到结果图像里

pixret[1] = curpixBri;

pixret[2] = curpixBri;

++pixidx;

pixret += 3;

}

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 < 1)

{

return false;

}

if (val1 > val2 && val1 > val2 + diff)

{

return true;

}

if (val2 > val1 && val2 > val1 + diff)

{

return true;

}

return false;

}

#endregion

}

}

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

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

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

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

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

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

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

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

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

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

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

  9. PHP控制连接打印机

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

随机推荐

  1. 如何使用PL/SQL进行远程数据库连接

    1.先找到Oracle数据库的安装地址然后找到network->ADMIN->tnsnames.ora文件 2.添加下面文件到tnsnames.ora文件中去,红色部分是需要修改的部分   ...

  2. HBase Shell操作

    Hbase 是一个分布式的.面向列的开源数据库,其实现是建立在google 的bigTable 理论之上,并基于hadoop HDFS文件系统.     Hbase不同于一般的关系型数据库(RDBMS ...

  3. linux基础1——网络配置入门

    1.IP地址配置 (1)临时IP更改 sudo ifconfig eth0 down    暂停接口 sudo ifconfig eth0 192.168.1.xx sudo ifconfig eth ...

  4. python3.x IDLE学习及基础语法(学习head first python 第一章)

    1. 使用Tab键可以显示IDLE提供的一些建议: 2. Alt-N 移至下一个代码语句,Alt-P 移至上一个代码语句: 3. 列表类似于C++里的链表,有插入函数insert(位置,数据项),在列 ...

  5. sql install error

    解决SQL Server 2008 R2安装过程中提示Could not open key的解决方法:以管理员身份运行CMD命令提示符,输入以下语句并运行就OK了secedit /configure ...

  6. Hibernate中evict方法和clear方法说明

    Hibernate中evict方法和clear方法说明 先创建一个对象,然后调用session.save方法,然后调用evict方法把该对象清除出缓存,最后提交事务.结果报错: Exception i ...

  7. jsp+servlet+mysql 实现简单的银行登录转账功能

    jsp+servlet+mysql 实现简单的银行登录转账功能 [前期的准备] html(登录界面),servlet(处理业务逻辑),jsp(主要实现界面),mysql(实现与数据库的简单的交互)先从 ...

  8. 监控数据库运行 - MS SQL 日常维护管理常用脚本(二)

    查看数据库登录名信息 use mastergoSELECT name AS LoginName , dbname AS DefaultDB , createdate AS CreateDate, up ...

  9. CMakeLists.txt for nginx

    project(nginx) cmake_minimum_required(VERSION 2.8) aux_source_directory(. SRC_LIST) aux_source_direc ...

  10. [python学习] 介绍python的property,以及为什么要用setter,一个小栗子

    python中的property是比较好用的. 先来一段代码 #-*- coding:utf-8 -*- class C(object): status_dict = { 1: 'accept', 2 ...