251029
This commit is contained in:
54
FATrace.App/UniCodeToZPL/CompressCode.cs
Normal file
54
FATrace.App/UniCodeToZPL/CompressCode.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩使用标记枚举值
|
||||
/// </summary>
|
||||
public enum CompressCode
|
||||
{
|
||||
G = 1,
|
||||
H = 2,
|
||||
I = 3,
|
||||
J = 4,
|
||||
K = 5,
|
||||
L = 6,
|
||||
M = 7,
|
||||
N = 8,
|
||||
O = 9,
|
||||
P = 10,
|
||||
Q = 11,
|
||||
R = 12,
|
||||
S = 13,
|
||||
T = 14,
|
||||
U = 15,
|
||||
V = 16,
|
||||
W = 17,
|
||||
X = 18,
|
||||
Y = 19,
|
||||
g = 20,
|
||||
h = 40,
|
||||
i = 60,
|
||||
j = 80,
|
||||
k = 100,
|
||||
l = 120,
|
||||
m = 140,
|
||||
n = 160,
|
||||
o = 180,
|
||||
p = 200,
|
||||
q = 220,
|
||||
r = 240,
|
||||
s = 260,
|
||||
t = 280,
|
||||
u = 300,
|
||||
v = 320,
|
||||
w = 340,
|
||||
x = 360,
|
||||
y = 380,
|
||||
z = 400,
|
||||
}
|
||||
}
|
||||
43
FATrace.App/UniCodeToZPL/CompressCodeInfo.cs
Normal file
43
FATrace.App/UniCodeToZPL/CompressCodeInfo.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩字符统计
|
||||
/// </summary>
|
||||
public class CompressCodeInfo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="code">压缩字符</param>
|
||||
/// <param name="count">数量</param>
|
||||
public CompressCodeInfo(string code, int count)
|
||||
{
|
||||
this.code = code;
|
||||
this.count = count;
|
||||
}
|
||||
private string code;
|
||||
/// <summary>
|
||||
/// 压缩的字符
|
||||
/// </summary>
|
||||
public string Code
|
||||
{
|
||||
get { return code; }
|
||||
set { code = value; }
|
||||
}
|
||||
private int count = 0;
|
||||
/// <summary>
|
||||
/// 数量
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return count; }
|
||||
set { count = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
20
FATrace.App/UniCodeToZPL/TextDirection.cs
Normal file
20
FATrace.App/UniCodeToZPL/TextDirection.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// 文字方向
|
||||
/// </summary>
|
||||
public enum TextDirection
|
||||
{
|
||||
Degree0 = 0,
|
||||
Degree45 = 45,
|
||||
Degree90 = 90,
|
||||
Degree180 = 180,
|
||||
Degree270 = 270,
|
||||
}
|
||||
}
|
||||
209
FATrace.App/UniCodeToZPL/UnicodeToZPLHelper.cs
Normal file
209
FATrace.App/UniCodeToZPL/UnicodeToZPLHelper.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// Unicode字符转化成对应的ZPL指令
|
||||
/// </summary>
|
||||
public class UnicodeToZPLHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成图片回调显示
|
||||
/// </summary>
|
||||
public static event Action<Image> OnViewImageCallBack;
|
||||
/// <summary>
|
||||
/// 未压缩算法处理
|
||||
/// Unicode字符转化成对应的ZPL指令
|
||||
/// </summary>
|
||||
/// <param name="content">文本内容</param>
|
||||
/// <param name="name">生成的图片名称,名称需要唯一</param>
|
||||
/// <param name="font">字体</param>
|
||||
/// <param name="textDirection">文字方向</param>
|
||||
/// <returns>
|
||||
/// 返回转换完未压缩的ZPL指令
|
||||
/// </returns>
|
||||
public static string UnCompressZPL(string content, string name, Font font, TextDirection textDirection)
|
||||
{
|
||||
Bitmap img = TextToBitmap(content, font, textDirection);
|
||||
if (textDirection != TextDirection.Degree0)
|
||||
{
|
||||
img = Rotate(img, (int)textDirection);
|
||||
}
|
||||
if (OnViewImageCallBack != null)
|
||||
{
|
||||
OnViewImageCallBack(img);
|
||||
}
|
||||
string imgCode = ConvertToZebraGRF(img);
|
||||
var totalBytes = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString(); //图形中的总字节数
|
||||
var lineBytes = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString(); //每行的字节数
|
||||
return string.Format("~DG{0}.GRF,{1},{2},{3}^XG{0}", name, totalBytes, lineBytes, imgCode);
|
||||
}
|
||||
/// <summary>
|
||||
/// 未压缩算法处理
|
||||
/// Unicode字符转化成对应的ZPL指令
|
||||
/// </summary>
|
||||
/// <param name="content">文本内容</param>
|
||||
/// <param name="name">生成的图片名称,名称需要唯一</param>
|
||||
/// <param name="textDirection">文字方向</param>
|
||||
/// <returns>
|
||||
/// 返回转换完未压缩的ZPL指令
|
||||
/// </returns>
|
||||
public static string UnCompressZPL(Bitmap img, string name, TextDirection textDirection)
|
||||
{
|
||||
if (textDirection != TextDirection.Degree0)
|
||||
{
|
||||
img = Rotate(img, (int)textDirection);
|
||||
}
|
||||
if (OnViewImageCallBack != null)
|
||||
{
|
||||
OnViewImageCallBack(img);
|
||||
}
|
||||
string imgCode = ConvertToZebraGRF(img);
|
||||
var totalBytes = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString(); //图形中的总字节数
|
||||
var lineBytes = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString(); //每行的字节数
|
||||
return string.Format("~DG{0}.GRF,{1},{2},{3}^XG{0}", name, totalBytes, lineBytes, imgCode);
|
||||
}
|
||||
/// <summary>
|
||||
/// 压缩算法处理
|
||||
/// Unicode字符转化成对应的ZPL指令
|
||||
/// </summary>
|
||||
/// <param name="content">文本内容</param>
|
||||
/// <param name="name">生成的图片名称,名称需要唯一</param>
|
||||
/// <param name="font">字体</param>
|
||||
/// <param name="textDirection">文字方向</param>
|
||||
/// <returns>
|
||||
/// 返回转换完压缩的ZPL指令
|
||||
/// </returns>
|
||||
public static string CompressZPL(string content, string name, Font font, TextDirection textDirection)
|
||||
{
|
||||
Bitmap img = TextToBitmap(content, font, textDirection);
|
||||
if (textDirection != TextDirection.Degree0)
|
||||
{
|
||||
img = Rotate(img, (int)textDirection);
|
||||
}
|
||||
if (OnViewImageCallBack != null)
|
||||
{
|
||||
OnViewImageCallBack(img);
|
||||
}
|
||||
string imgCode = ConvertToZebraGRF(img);
|
||||
imgCode = ZebraCompress.ZebraCompressCode(imgCode);
|
||||
var totalBytes = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString(); //图形中的总字节数
|
||||
var lineBytes = (img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)).ToString(); //每行的字节数
|
||||
return string.Format("~DG{0}.GRF,{1},{2},{3}^XG{0}", name, totalBytes, lineBytes, imgCode);
|
||||
}
|
||||
/// <summary>
|
||||
/// 把文字转换才Bitmap
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="font"></param>
|
||||
/// <returns></returns>
|
||||
private static Bitmap TextToBitmap(string text, Font font, TextDirection textDirection)
|
||||
{
|
||||
StringFormat format = new StringFormat(StringFormatFlags.NoClip);
|
||||
Bitmap bitmap = new Bitmap(1, 1);
|
||||
Graphics graphics = Graphics.FromImage(bitmap);
|
||||
SizeF sizef = graphics.MeasureString(text, font, PointF.Empty, format);
|
||||
int width = (int)(sizef.Width + 1);
|
||||
int height = (int)(sizef.Height + 1);
|
||||
Rectangle rect = new Rectangle(0, 0, width, height);
|
||||
bitmap.Dispose();
|
||||
bitmap = new Bitmap(width, height);
|
||||
graphics = Graphics.FromImage(bitmap);
|
||||
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;//使用ClearType字体功能
|
||||
graphics.FillRectangle(new SolidBrush(Color.White), rect);
|
||||
graphics.DrawString(text, font, Brushes.Black, rect, format);
|
||||
return bitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// 以逆时针为方向对图像进行旋转
|
||||
/// </summary>
|
||||
/// <param name="b">位图流</param>
|
||||
/// <param name="angle">旋转角度[0,360](前台给的)</param>
|
||||
/// <returns></returns>
|
||||
private static Bitmap Rotate(Bitmap b, int angle)
|
||||
{
|
||||
angle = angle % 360;
|
||||
//弧度转换
|
||||
double radian = angle * Math.PI / 180.0;
|
||||
double cos = Math.Cos(radian);
|
||||
double sin = Math.Sin(radian);
|
||||
//原图的宽和高
|
||||
int w = b.Width;
|
||||
int h = b.Height;
|
||||
int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));
|
||||
int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));
|
||||
//目标位图
|
||||
Bitmap dsImage = new Bitmap(W, H);
|
||||
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage);
|
||||
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
|
||||
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
||||
//计算偏移量
|
||||
Point Offset = new Point((W - w) / 2, (H - h) / 2);
|
||||
//构造图像显示区域:让图像的中心与窗口的中心点一致
|
||||
Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h);
|
||||
Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
|
||||
g.TranslateTransform(center.X, center.Y);
|
||||
g.RotateTransform(360 - angle);
|
||||
//恢复图像在水平和垂直方向的平移
|
||||
g.TranslateTransform(-center.X, -center.Y);
|
||||
g.DrawImage(b, rect);
|
||||
//重至绘图的所有变换
|
||||
g.ResetTransform();
|
||||
g.Save();
|
||||
g.Dispose();
|
||||
return dsImage;
|
||||
}
|
||||
/// <summary>
|
||||
/// 将BitMap图片转化成对应的灰度图片
|
||||
/// 取灰度分界中间值,作为黑白像素点的判断,187数值比较合适
|
||||
/// </summary>
|
||||
/// <param name="bitMap"></param>
|
||||
/// <returns></returns>
|
||||
private static unsafe string ConvertToZebraGRF(Bitmap bitMap)
|
||||
{
|
||||
System.Text.StringBuilder builder = new StringBuilder();
|
||||
BitmapData data = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), ImageLockMode.ReadOnly,
|
||||
PixelFormat.Format24bppRgb);
|
||||
|
||||
var bp = (byte*)data.Scan0.ToPointer();
|
||||
for (int i = 0; i < data.Height; i++)
|
||||
{
|
||||
int count = 0;
|
||||
int tempData = 0;
|
||||
for (int j = 0; j < data.Width; j++)
|
||||
{
|
||||
float gray = 0.11F * bp[i * data.Stride + j * 3] + 0.59F * bp[i * data.Stride + j * 3 + 1] +
|
||||
0.3F * bp[i * data.Stride + j * 3 + 2];
|
||||
tempData = tempData * 2;
|
||||
if (gray < 187)
|
||||
{
|
||||
tempData++;
|
||||
}
|
||||
count++;
|
||||
if (j == (data.Width - 1))
|
||||
{
|
||||
if (count < 8)
|
||||
{
|
||||
tempData = tempData * (2 ^ (8 - (int)count));
|
||||
string temp = tempData.ToString("X").PadLeft(2, '0');
|
||||
builder.Append(temp);
|
||||
tempData = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
if (count >= 8)
|
||||
{
|
||||
string temp = tempData.ToString("X").PadLeft(2, '0');
|
||||
builder.Append(temp);
|
||||
tempData = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
bitMap.UnlockBits(data);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
182
FATrace.App/UniCodeToZPL/ZebraCompress.cs
Normal file
182
FATrace.App/UniCodeToZPL/ZebraCompress.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// 编码压缩处理
|
||||
/// </summary>
|
||||
internal class ZebraCompress
|
||||
{
|
||||
/// <summary>
|
||||
/// 编码处理压缩算法
|
||||
/// </summary>
|
||||
/// <param name="code">需要压缩的16进制编码</param>
|
||||
/// <returns>
|
||||
/// 返回压缩完的算法
|
||||
/// </returns>
|
||||
public static string ZebraCompressCode(string code)
|
||||
{
|
||||
List<CompressCodeInfo> list = new List<CompressCodeInfo>();
|
||||
char flag = '.';
|
||||
int charCount = 0;
|
||||
for (int i = 0; i < code.Length; i++)
|
||||
{
|
||||
char item = code[i];
|
||||
if (item != flag)
|
||||
{
|
||||
if (charCount > 0)
|
||||
{
|
||||
list.Add(new CompressCodeInfo(flag.ToString(), charCount));
|
||||
}
|
||||
charCount = 0;
|
||||
flag = item;
|
||||
}
|
||||
charCount += 1;
|
||||
if (i == code.Length - 1)
|
||||
{
|
||||
if (charCount > 0)
|
||||
{
|
||||
list.Add(new CompressCodeInfo(flag.ToString(), charCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
CompressCodeInfo item = list[i];
|
||||
if (item.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.Count == 1)
|
||||
{
|
||||
builder.Append(item.Code);
|
||||
continue;
|
||||
}
|
||||
if (item.Count <= 20)
|
||||
{
|
||||
builder.AppendFormat("{0}{1}", ((CompressCode)item.Count).ToString(), item.Code);
|
||||
continue;
|
||||
}
|
||||
int count = 0;
|
||||
while (true)
|
||||
{
|
||||
if (item.Count - count <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (item.Count - count < 20)
|
||||
{
|
||||
builder.AppendFormat("{0}{1}", ((CompressCode)(item.Count - count)).ToString(), item.Code);
|
||||
break;
|
||||
}
|
||||
if ((item.Count - count) >= (int)CompressCode.z)
|
||||
{
|
||||
count += (int)CompressCode.z;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.z).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.y)
|
||||
{
|
||||
count += (int)CompressCode.y;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.y).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.x)
|
||||
{
|
||||
count += (int)CompressCode.x;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.x).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.w)
|
||||
{
|
||||
count += (int)CompressCode.w;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.w).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.v)
|
||||
{
|
||||
count += (int)CompressCode.v;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.v).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.u)
|
||||
{
|
||||
count += (int)CompressCode.u;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.u).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.t)
|
||||
{
|
||||
count += (int)CompressCode.t;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.t).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.s)
|
||||
{
|
||||
count += (int)CompressCode.s;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.s).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.r)
|
||||
{
|
||||
count += (int)CompressCode.r;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.r).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.q)
|
||||
{
|
||||
count += (int)CompressCode.q;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.q).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.p)
|
||||
{
|
||||
count += (int)CompressCode.p;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.p).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.o)
|
||||
{
|
||||
count += (int)CompressCode.o;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.o).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.n)
|
||||
{
|
||||
count += (int)CompressCode.n;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.n).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.m)
|
||||
{
|
||||
count += (int)CompressCode.m;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.m).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.l)
|
||||
{
|
||||
count += (int)CompressCode.l;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.l).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.k)
|
||||
{
|
||||
count += (int)CompressCode.k;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.k).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.j)
|
||||
{
|
||||
count += (int)CompressCode.j;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.j).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.i)
|
||||
{
|
||||
count += (int)CompressCode.i;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.i).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.h)
|
||||
{
|
||||
count += (int)CompressCode.h;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.h).ToString(), item.Code);
|
||||
}
|
||||
else if ((item.Count - count) >= (int)CompressCode.g)
|
||||
{
|
||||
count += (int)CompressCode.g;
|
||||
builder.AppendFormat("{0}{1}", (CompressCode.g).ToString(), item.Code);
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
462
FATrace.App/UniCodeToZPL/ZebraUnity.cs
Normal file
462
FATrace.App/UniCodeToZPL/ZebraUnity.cs
Normal file
@@ -0,0 +1,462 @@
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FATrace.App.UniCodeToZPL
|
||||
{
|
||||
/// <summary>
|
||||
/// 斑马工具类,把图像转换成斑马打印机的命令
|
||||
/// 网上获取但是当前项目没有使用过
|
||||
/// https://gitcode.com/open-source-toolkit/25bfe
|
||||
/// </summary>
|
||||
public class ZebraUnity
|
||||
{
|
||||
#region 定义私有字段
|
||||
/// <summary>
|
||||
/// 线程锁,防止多线程调用。
|
||||
/// </summary>
|
||||
private static object SyncRoot = new object();
|
||||
/// <summary>
|
||||
/// ZPL压缩字典
|
||||
/// </summary>
|
||||
private static List<KeyValuePair<char, int>> compressDictionary = new List<KeyValuePair<char, int>>();
|
||||
#endregion
|
||||
|
||||
#region 构造方法
|
||||
|
||||
static ZebraUnity()
|
||||
{
|
||||
InitCompressCode();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 定义属性
|
||||
/// <summary>
|
||||
/// 图像的二进制数据
|
||||
/// </summary>
|
||||
public static byte[] GraphBuffer { get; set; }
|
||||
/// <summary>
|
||||
/// 图像的宽度
|
||||
/// </summary>
|
||||
private static int GraphWidth { get; set; }
|
||||
/// <summary>
|
||||
/// 图像的高度
|
||||
/// </summary>
|
||||
private static int GraphHeight { get; set; }
|
||||
private static int RowSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return (((GraphWidth) + 31) >> 5) << 2;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 每行的字节数
|
||||
/// </summary>
|
||||
private static int RowRealBytesCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((GraphWidth % 8) > 0)
|
||||
{
|
||||
return GraphWidth / 8 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GraphWidth / 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 位图转斑马指令字符串
|
||||
/// <summary>
|
||||
/// 位图转斑马指令字符串
|
||||
/// </summary>
|
||||
/// <param name="bitmap">位图数据</param>
|
||||
/// <param name="totalBytes">总共的字节数</param>
|
||||
/// <param name="rowBytes">每行的字节数</param>
|
||||
/// <returns>斑马ZPL 2命令</returns>
|
||||
public static string BmpToZpl(byte[] bitmap, out int totalBytes, out int rowBytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
GraphBuffer = bitmap;
|
||||
byte[] bmpData = getBitmapData();
|
||||
string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty);
|
||||
string textBitmap = CompressLZ77(textHex);
|
||||
totalBytes = GraphHeight * RowRealBytesCount;
|
||||
rowBytes = RowRealBytesCount;
|
||||
return textBitmap;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 位图转ZPL指令
|
||||
/// </summary>
|
||||
/// <param name="bitmap">位图</param>
|
||||
/// <param name="totalBytes">返回参数总共字节数</param>
|
||||
/// <param name="rowBytes">返回参数每行的字节数</param>
|
||||
/// <returns>ZPL命令</returns>
|
||||
public static string BmpToZpl(Image bitmap, out int totalBytes, out int rowBytes)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
bitmap.Save(stream, ImageFormat.Bmp);
|
||||
return BmpToZpl(stream.ToArray(), out totalBytes, out rowBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据图片生成图片的ASCII 十六进制
|
||||
/// </summary>
|
||||
/// <param name="sourceBmp">原始图片</param>
|
||||
/// <param name="totalBytes">总共字节数</param>
|
||||
/// <param name="rowBytes">每行的字节数</param>
|
||||
/// <returns>ASCII 十六进制</returns>
|
||||
public static string BitmapToHex(Image sourceBmp, out int totalBytes, out int rowBytes)
|
||||
{
|
||||
// 转成单色图
|
||||
Bitmap grayBmp = ConvertToGrayscale(sourceBmp as Bitmap);
|
||||
// 锁定位图数据
|
||||
Rectangle rect = new Rectangle(0, 0, grayBmp.Width, grayBmp.Height);
|
||||
System.Drawing.Imaging.BitmapData bmpData = grayBmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, grayBmp.PixelFormat);
|
||||
// 获取位图数据第一行的起始地址
|
||||
IntPtr ptr = bmpData.Scan0;
|
||||
// 定义数组以存放位图的字节流数据
|
||||
// 处理像素宽对应的字节数,如不为8的倍数,则对最后一个字节补0
|
||||
int width = (int)Math.Ceiling(grayBmp.Width / 8.0);
|
||||
// 获取位图实际的字节宽,这个值因为要考虑4的倍数关系,可能大于width
|
||||
int stride = Math.Abs(bmpData.Stride);
|
||||
// 计算位图数据实际所占的字节数,并定义数组
|
||||
int bitmapDataLength = stride * grayBmp.Height;
|
||||
byte[] ImgData = new byte[bitmapDataLength];
|
||||
// 从位图文件复制图像数据到数组,从实际图像数据的第一行开始;因ptr指针而无需再考虑行倒序存储的处理
|
||||
System.Runtime.InteropServices.Marshal.Copy(ptr, ImgData, 0, bitmapDataLength);
|
||||
// 计算异或操作数,以处理包含图像数据但又有补0操作的那个字节
|
||||
byte mask = 0xFF;
|
||||
// 计算这个字节补0的个数
|
||||
//int offset = 8 * width - grayBmp.Width;
|
||||
int offset = 8 - (grayBmp.Width % 8);
|
||||
//offset %= 8;
|
||||
offset = offset % 8;
|
||||
// 按补0个数对0xFF做相应位数的左移位操作
|
||||
mask <<= (byte)offset;
|
||||
// 图像反色处理
|
||||
for (int j = 0; j < grayBmp.Height; j++)
|
||||
{
|
||||
for (int i = 0; i < stride; i++)
|
||||
{
|
||||
if (i < width - 1) //无补0的图像数据
|
||||
{
|
||||
ImgData[j * stride + i] ^= 0xFF;
|
||||
}
|
||||
else if (i == width - 1) //有像素的最后一个字节,可能有补0
|
||||
{
|
||||
ImgData[j * stride + i] ^= mask;
|
||||
}
|
||||
else //为满足行字节宽为4的倍数而最后补的字节
|
||||
{
|
||||
//ImgData[j * stride + i] = 0x00;
|
||||
ImgData[j * stride + i] ^= 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 将位图数据转换为16进制的ASCII字符
|
||||
string zplString = BitConverter.ToString(ImgData);
|
||||
zplString = CompressLZ77(zplString.Replace("-", string.Empty));
|
||||
totalBytes = bitmapDataLength;
|
||||
rowBytes = stride;
|
||||
return zplString;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 获取单色位图数据
|
||||
/// <summary>
|
||||
/// 获取单色位图数据
|
||||
/// </summary>
|
||||
/// <param name="pimage"></param>
|
||||
/// <returns></returns>
|
||||
private static Bitmap ConvertToGrayscale(Bitmap pimage)
|
||||
{
|
||||
Bitmap source = null;
|
||||
|
||||
// If original bitmap is not already in 32 BPP, ARGB format, then convert
|
||||
if (pimage.PixelFormat != PixelFormat.Format32bppArgb)
|
||||
{
|
||||
source = new Bitmap(pimage.Width, pimage.Height, PixelFormat.Format32bppArgb);
|
||||
source.SetResolution(pimage.HorizontalResolution, pimage.VerticalResolution);
|
||||
using (Graphics g = Graphics.FromImage(source))
|
||||
{
|
||||
g.DrawImageUnscaled(pimage, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
source = pimage;
|
||||
}
|
||||
|
||||
// Lock source bitmap in memory
|
||||
BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Copy image data to binary array
|
||||
int imageSize = sourceData.Stride * sourceData.Height;
|
||||
byte[] sourceBuffer = new byte[imageSize];
|
||||
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
|
||||
|
||||
// Unlock source bitmap
|
||||
source.UnlockBits(sourceData);
|
||||
|
||||
// Create destination bitmap
|
||||
Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
|
||||
|
||||
// Lock destination bitmap in memory
|
||||
BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
|
||||
|
||||
// Create destination buffer
|
||||
imageSize = destinationData.Stride * destinationData.Height;
|
||||
byte[] destinationBuffer = new byte[imageSize];
|
||||
|
||||
int sourceIndex = 0;
|
||||
int destinationIndex = 0;
|
||||
int pixelTotal = 0;
|
||||
byte destinationValue = 0;
|
||||
int pixelValue = 128;
|
||||
int height = source.Height;
|
||||
int width = source.Width;
|
||||
int threshold = 500;
|
||||
|
||||
// Iterate lines
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
sourceIndex = y * sourceData.Stride;
|
||||
destinationIndex = y * destinationData.Stride;
|
||||
destinationValue = 0;
|
||||
pixelValue = 128;
|
||||
|
||||
// Iterate pixels
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
// Compute pixel brightness (i.e. total of Red, Green, and Blue values)
|
||||
pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3];
|
||||
if (pixelTotal > threshold)
|
||||
{
|
||||
destinationValue += (byte)pixelValue;
|
||||
}
|
||||
if (pixelValue == 1)
|
||||
{
|
||||
destinationBuffer[destinationIndex] = destinationValue;
|
||||
destinationIndex++;
|
||||
destinationValue = 0;
|
||||
pixelValue = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixelValue >>= 1;
|
||||
}
|
||||
sourceIndex += 4;
|
||||
}
|
||||
if (pixelValue != 128)
|
||||
{
|
||||
destinationBuffer[destinationIndex] = destinationValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy binary image data to destination bitmap
|
||||
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
|
||||
|
||||
// Unlock destination bitmap
|
||||
destination.UnlockBits(destinationData);
|
||||
|
||||
// Dispose of source if not originally supplied bitmap
|
||||
if (source != pimage)
|
||||
{
|
||||
source.Dispose();
|
||||
}
|
||||
|
||||
// Return
|
||||
return destination;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static byte[] getBitmapData()
|
||||
{
|
||||
MemoryStream srcStream = new MemoryStream();
|
||||
MemoryStream dstStream = new MemoryStream();
|
||||
Bitmap srcBmp = null;
|
||||
Bitmap dstBmp = null;
|
||||
byte[] srcBuffer = null;
|
||||
byte[] dstBuffer = null;
|
||||
byte[] result = null;
|
||||
try
|
||||
{
|
||||
srcStream = new MemoryStream(GraphBuffer);
|
||||
srcBmp = Bitmap.FromStream(srcStream) as Bitmap;
|
||||
srcBuffer = srcStream.ToArray();
|
||||
GraphWidth = srcBmp.Width;
|
||||
GraphHeight = srcBmp.Height;
|
||||
//dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed);
|
||||
dstBmp = ConvertToGrayscale(srcBmp);
|
||||
dstBmp.Save(dstStream, ImageFormat.Bmp);
|
||||
dstBuffer = dstStream.ToArray();
|
||||
|
||||
result = dstBuffer;
|
||||
|
||||
int bfOffBits = BitConverter.ToInt32(dstBuffer, 10);
|
||||
result = new byte[GraphHeight * RowRealBytesCount];
|
||||
|
||||
////读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。
|
||||
for (int i = 0; i < GraphHeight; i++)
|
||||
{
|
||||
int sindex = bfOffBits + (GraphHeight - 1 - i) * RowSize;
|
||||
int dindex = i * RowRealBytesCount;
|
||||
Array.Copy(dstBuffer, sindex, result, dindex, RowRealBytesCount);
|
||||
}
|
||||
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
result[i] ^= 0xFF;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (srcStream != null)
|
||||
{
|
||||
srcStream.Dispose();
|
||||
srcStream = null;
|
||||
}
|
||||
if (dstStream != null)
|
||||
{
|
||||
dstStream.Dispose();
|
||||
dstStream = null;
|
||||
}
|
||||
if (srcBmp != null)
|
||||
{
|
||||
srcBmp.Dispose();
|
||||
srcBmp = null;
|
||||
}
|
||||
if (dstBmp != null)
|
||||
{
|
||||
dstBmp.Dispose();
|
||||
dstBmp = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LZ77图像字节流压缩方法
|
||||
private static string CompressLZ77(string text)
|
||||
{
|
||||
//将转成16进制的文本进行压缩
|
||||
string result = string.Empty;
|
||||
char[] arrChar = text.ToCharArray();
|
||||
int count = 1;
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
{
|
||||
if (arrChar[i - 1] == arrChar[i])
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += convertNumber(count) + arrChar[i - 1];
|
||||
count = 1;
|
||||
}
|
||||
if (i == text.Length - 1)
|
||||
{
|
||||
result += convertNumber(count) + arrChar[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string DecompressLZ77(string text)
|
||||
{
|
||||
string result = string.Empty;
|
||||
char[] arrChar = text.ToCharArray();
|
||||
int count = 0;
|
||||
for (int i = 0; i < arrChar.Length; i++)
|
||||
{
|
||||
if (isHexChar(arrChar[i]))
|
||||
{
|
||||
//十六进制值
|
||||
result += new string(arrChar[i], count == 0 ? 1 : count);
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//压缩码
|
||||
int value = GetCompressValue(arrChar[i]);
|
||||
count += value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int GetCompressValue(char c)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < compressDictionary.Count; i++)
|
||||
{
|
||||
if (c == compressDictionary[i].Key)
|
||||
{
|
||||
result = compressDictionary[i].Value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool isHexChar(char c)
|
||||
{
|
||||
return c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103;
|
||||
}
|
||||
|
||||
private static string convertNumber(int count)
|
||||
{
|
||||
//将连续的数字转换成LZ77压缩代码,如000可用I0表示。
|
||||
string result = string.Empty;
|
||||
if (count > 1)
|
||||
{
|
||||
while (count > 0)
|
||||
{
|
||||
for (int i = compressDictionary.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (count >= compressDictionary[i].Value)
|
||||
{
|
||||
result += compressDictionary[i].Key;
|
||||
count -= compressDictionary[i].Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void InitCompressCode()
|
||||
{
|
||||
//G H I J K L M N O P Q R S T U V W X Y 对应1,2,3,4……18,19。
|
||||
//g h i j k l m n o p q r s t u v w x y z 对应20,40,60,80……340,360,380,400。
|
||||
for (int i = 0; i < 19; i++)
|
||||
{
|
||||
compressDictionary.Add(new KeyValuePair<char, int>(Convert.ToChar(71 + i), i + 1));
|
||||
}
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
compressDictionary.Add(new KeyValuePair<char, int>(Convert.ToChar(103 + i), (i + 1) * 20));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user