using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JXUtil
{
public class BarCode
{
private Hashtable _Code39 = new Hashtable();
/// <summary>
/// 内容
/// </summary>
public string Text { get; set; }
/// <summary>
/// 放大倍数
/// </summary>
public byte Magnify { get; set; }
/// <summary>
/// 图形高
/// </summary>
public int Height { get; set; }
/// <summary>
/// 字体大小
/// </summary>
public Font ViewFont { get; set; }
public BarCode()
{
_Code39.Add("A", "");
_Code39.Add("B", "");
_Code39.Add("C", "");
_Code39.Add("D", "");
_Code39.Add("E", "");
_Code39.Add("F", "");
_Code39.Add("G", "");
_Code39.Add("H", "");
_Code39.Add("I", "");
_Code39.Add("J", "");
_Code39.Add("K", "");
_Code39.Add("L", "");
_Code39.Add("M", "");
_Code39.Add("N", "");
_Code39.Add("O", "");
_Code39.Add("P", "");
_Code39.Add("Q", "");
_Code39.Add("R", "");
_Code39.Add("S", "");
_Code39.Add("T", "");
_Code39.Add("U", "");
_Code39.Add("V", "");
_Code39.Add("W", "");
_Code39.Add("X", "");
_Code39.Add("Y", "");
_Code39.Add("Z", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("", "");
_Code39.Add("+", "");
_Code39.Add("-", "");
_Code39.Add("*", "");
_Code39.Add("/", "");
_Code39.Add("%", "");
_Code39.Add("&", "");
_Code39.Add(".", "");
_Code39.Add(" ", "");
}
public enum Code39Model
{
/// <summary>
/// 基本类别 1234567890ABC
/// </summary>
Code39Normal,
/// <summary>
/// 全ASCII方式 +A+B 来表示小写
/// </summary>
Code39FullAscII
}
/// <summary>
/// 获得条码图形
/// </summary>
/// <param name="text">文字信息</param>
/// <param name="model">类别</param>
/// <param name="stat">是否增加前后*号</param>
/// <returns>图形</returns>
public Bitmap GetCodeImage(Code39Model model, bool star)
{
string textVal = "";
string textCode = "";
char[] charVal = null;
switch (model)
{
case Code39Model.Code39Normal:
textVal = Text.ToUpper();
break;
default:
charVal = Text.ToCharArray();
for (int i = ; i != charVal.Length; i++)
{
if ((int)charVal[i] >= && (int)charVal[i] <= )
{
textVal += "+" + charVal[i].ToString().ToUpper();
}
else
{
textVal += charVal[i].ToString();
}
}
break;
}
charVal = textVal.ToCharArray();
if (star == true) textCode += _Code39["*"];
for (int i = ; i != charVal.Length; i++)
{
if (star == true && charVal[i] == '*') throw new Exception("带有起始符号不能出现*");
object _CharCode = _Code39[charVal[i].ToString()];
if (_CharCode == null) throw new Exception("不可用的字符" + charVal[i].ToString());
textCode += _CharCode.ToString();
}
if (star == true) textCode += _Code39["*"];
Bitmap bmp = GetImage(textCode);
GetViewImage(bmp, Text);
return bmp;
}
/// <summary>
/// 绘制编码图形
/// </summary>
/// <param name="text">编码</param>
/// <returns>图形</returns>
private Bitmap GetImage(string text)
{
char[] val = text.ToCharArray();
//宽 == 需要绘制的数量*放大倍数 + 两个字的宽
Bitmap codeImg = new Bitmap(val.Length * ((int)Magnify + ), (int)Height);
Graphics graph = Graphics.FromImage(codeImg);
graph.FillRectangle(Brushes.White, new Rectangle(, , codeImg.Width, codeImg.Height));
int len = ;
for (int i = ; i != val.Length; i++)
{
int width = Magnify + ;
if (val[i] == '')
{
graph.FillRectangle(Brushes.Black, new Rectangle(len, , width, Height));
}
else
{
graph.FillRectangle(Brushes.White, new Rectangle(len, , width, Height));
}
len += width;
}
graph.Dispose();
return codeImg;
}
/// <summary>
/// 绘制文字
/// </summary>
/// <param name="codeImage">图形</param>
/// <param name="text">文字</param>
private void GetViewImage(Bitmap codeImage, string text)
{
if (ViewFont == null) return;
Graphics graphic = Graphics.FromImage(codeImage);
SizeF fontSize = graphic.MeasureString(text, ViewFont);
if (fontSize.Width > codeImage.Width || fontSize.Height > codeImage.Height - )
{
graphic.Dispose();
return;
}
int starHeight = codeImage.Height - (int)fontSize.Height;
graphic.FillRectangle(Brushes.White, new Rectangle(, starHeight, codeImage.Width, (int)fontSize.Height));
int _StarWidth = (codeImage.Width - (int)fontSize.Width) / ;
graphic.DrawString(text, ViewFont, Brushes.Black, _StarWidth, starHeight);
graphic.Dispose();
}
}
public class BarCode128
{
// ASCII从32到127对应的条码区,由3个条、3个空、共11个单元构成,符号内含校验码
private string[] Code128Encoding = new string[] {
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", ""
};
private const string Code128Stop = "", Code128End = ""; //固定码尾
private enum Code128ChangeModes { CodeA = , CodeB = , CodeC = }; //变更
private enum Code128StartModes { CodeUnset = , CodeA = , CodeB = , CodeC = };//各类编码的码头
/// <summary>
/// 绘制Code128码(以像素为单位)
/// </summary>
public int EncodeBarcode(string code, System.Drawing.Graphics g, int x, int y, int width, int height, bool showText)
{
if (string.IsNullOrEmpty(code)) new Exception("条码不能为空");
List<int> encoded = CodetoEncoded(code); //1.拆分转义
encoded.Add(CheckDigitCode128(encoded)); //2.加入校验码
string encodestring = EncodeString(encoded); //3.编码
if (showText) //计算文本的大小,字体占图像的1/4高
{
Font font = new System.Drawing.Font("宋体", height / 4F, System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel, ((byte)()));
SizeF size = g.MeasureString(code, font);
height = height - (int)size.Height;
int _StarWidth = (width - (int)size.Width) / ;
g.DrawString(code, font, System.Drawing.Brushes.Black, _StarWidth, height);
int w = DrawBarCode(g, encodestring, x, y, width, height); //4.绘制
return ((int)size.Width > w ? (int)size.Width : w);
}
else
return DrawBarCode(g, encodestring, x, y, width, height); //4.绘制
}
//1.检测并将字符串拆分并加入码头
private List<int> CodetoEncoded(string code)
{
List<int> encoded = new List<int>();
int type = ;//2:B类,3:C类
for (int i = ; code.Length > ; i++)
{
int k = isNumber(code);
if (k >= ) //连续偶个数字可优先使用C类(其实并不定要转C类,但能用C类时条码会更短)
{
if (type == ) encoded.Add((int)Code128StartModes.CodeC); //加入码头
else if (type != ) encoded.Add((int)(Code128ChangeModes.CodeC)); //转义
type = ;
for (int j = ; j < k; j = j + ) //两位数字合为一个码身
{
encoded.Add(Int32.Parse(code.Substring(, )));
code = code.Substring();
}
}
else
{
if ((int)code[] < || (int)code[] > ) throw new Exception("字符串必须是数字或字母");
if (type == ) encoded.Add((int)Code128StartModes.CodeB); //加入码头
else if (type != ) encoded.Add((int)(Code128ChangeModes.CodeB)); //转义
type = ;
encoded.Add((int)code[] - );//字符串转为ASCII-32
code = code.Substring();
}
}
return encoded;
}
//2.校验码
private int CheckDigitCode128(List<int> encoded)
{
int check = encoded[];
for (int i = ; i < encoded.Count; i++)
check = check + (encoded[i] * i);
return (check % );
}
//2.编码(对应Code128Encoding数组)
private string EncodeString(List<int> encoded)
{
string encodedString = "";
for (int i = ; i < encoded.Count; i++)
{
encodedString += Code128Encoding[encoded[i]];
}
encodedString += Code128Stop + Code128End; // 加入结束码
return encodedString;
}
//4.绘制条码(返回实际图像宽度)
private int DrawBarCode(System.Drawing.Graphics g, string encodeString, int x, int y, int width, int height)
{
int w = width / encodeString.Length;
for (int i = ; i < encodeString.Length; i++)
{
g.FillRectangle(encodeString[i] == '' ? System.Drawing.Brushes.White : System.Drawing.Brushes.Black, x, y, w, height);
x += w;
}
return w * (encodeString.Length + );
}
//检测是否连续偶个数字,返回连续数字的长度
private int isNumber(string code)
{
int k = ;
for (int i = ; i < code.Length; i++)
{
if (char.IsNumber(code[i]))
k++;
else
break;
}
if (k % != ) k--;
return k;
}
/// <summary>
/// 绘制Code128码到图片
/// </summary>
public Image EncodeBarcode(string code, int width, int height, bool showText)
{
Bitmap image = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(image))
{
g.Clear(Color.White);
int w = EncodeBarcode(code, g, , , width, height, showText);
Bitmap image2 = new Bitmap(w, height); //剪切多余的空白;
using (Graphics g2 = Graphics.FromImage(image2))
{
g2.DrawImage(image, , );
return image2;
}
}
}
/// <summary>
/// 绘制Code128码到流
/// </summary>
public byte[] EncodeBarcodeByte(string code, int width, int height, bool showText)
{
Image image = EncodeBarcode(code, width, height, showText);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] byteImage = ms.ToArray();
ms.Close();
image.Dispose();
return byteImage;
}
}
}