Code 39 was the first alphanumeric symbology developed, and is widely used in industrial settings. Code 39 has two different element widths, wide and narrow, which are usually specified by giving the narrow width and the narrow/wide ratio. Each Code 39 character has five bars and four spaces for a total of nine elements. Of the nine elements, three are wide and six are narrow, leading to the name Code 39 (3 of 9). Each character is followed by an inter-character gap, usually equal to the width of a narrow element. The 44 characters in the Code 39 symbology are listed below:
Character
Pattern (bsbsbsbsb)
1
wnnwnnnnw
2
nnwwnnnnw
3
wnwwnnnnn
4
nnnwwnnnw
5
wnnwwnnnn
6
nnwwwnnnn
7
nnnwnnwnw
8
wnnwnnwnn
9
nnwwnnwnn
0
nnnwwnwnn
A
wnnnnwnnw
B
nnwnnwnnw
C
wnwnnwnnn
D
nnnnwwnnw
E
wnnnwwnnn
F
nnwnwwnnn
G
nnnnnwwnw
H
wnnnnwwnn
I
nnwnnwwnn
J
nnnnwwwnn
K
wnnnnnnww
L
nnwnnnnww
M
wnwnnnnwn
N
nnnnwnnww
O
wnnnwnnwn
P
nnwnwnnwn
Q
nnnnnnwww
R
wnnnnnwwn
S
nnwnnnwwn
T
nnnnwnwwn
U
wwnnnnnnw
V
nwwnnnnnw
W
wwwnnnnnn
X
nwnnwnnnw
Y
wwnnwnnnn
Z
nwwnwnnnn
-
nwnnnnwnw
.
wwnnnnwnn
SPACE
nwwnnnwnn
*
nwnnwnwnn
$
nwnwnwnnn
/
nwnwnnnwn
+
nwnnnwnwn
%
nnnwnwnwn
A Code 39 message begins and ends with an asterisk, which serves as this symbologies start/stop code. A sample Code 39 message “DATA” is pictured below complete with start and stop codes.
http://hi.baidu.com/hoping/blog/item/3e7873f0cfe9e7ada50f523d.html
39码是公元1974年发展出来的条形码系统,是一种可供使用者双向扫瞄的分布式条形码,也就是说相临两数据码之间,必须包含一个不具任何意义的空白(或细白,其逻辑值为0。标准的39码是由起始安全空间、起始码、数据码、可忽略不计的检查码、终止安全空间及终止码所构成。
编码规则:
39码总共可表示的字符范围包含有:0~9的数字,A~Z的英文字母,以及“+”、“-”、“*”、“/”、“%”、“$”、“.”等特殊符号,再加上空格符“ ”,共计44组编码,每一个字符编码都是按照5条四空,其中有3个宽单元,即藉由九条不同排列的线条编码而得。可分为四类:
粗黑线:11
细黑线:1
粗白线:00
细白线:0
而且规范中的规定了每个字符所对应的编码对应表,所以生成条码实质上只是根据每个字符的编码画出宽度不同的线而已。
相关网页:http://www.codeproject.com/bitmap/barcode1.asp
例程:
namespace Barcode
{
/// <summary>
/// Code39:生成39条形码。
/// </summary>
public class Code39
{
//对应码表
private Hashtable Decode;
private Hashtable CheckCode;
//每个字符间的间隔符
private string SPARATOR="0";
//float WidthUNIT= 0.25f;//宽度单位 mm
public int WidthCU = 3; //粗线和宽间隙宽度
public int WidthXI = 1; //细线和窄间隙宽度
public int xCoordinate =10;//75; //条码起始坐标
public int LineHeight=60;
private int Height=0;
private int Width=0;
public Code39()
{
Decode=new Hashtable();
Decode.Add("0","000110100");
Decode.Add("1","100100001");
Decode.Add("2","001100001");
Decode.Add("3","101100000");
Decode.Add("4","000110001");
Decode.Add("5","100110000");
Decode.Add("6","001110000");
Decode.Add("7","000100101");
Decode.Add("8","100100100");
Decode.Add("9","001100100");
Decode.Add("A","100001001");
Decode.Add("B","001001001");
Decode.Add("C","101001000");
Decode.Add("D","000011001");
Decode.Add("E","100011000");
Decode.Add("F","001011000");
Decode.Add("G","000001101");
Decode.Add("H","100001100");
Decode.Add("I","001001101");
Decode.Add("J","000011100");
Decode.Add("K","100000011");
Decode.Add("L","001000011");
Decode.Add("M","101000010");
Decode.Add("N","000010011");
Decode.Add("O","100010010");
Decode.Add("P","001010010");
Decode.Add("Q","000000111");
Decode.Add("R","100000110");
Decode.Add("S","001000110");
Decode.Add("T","000010110");
Decode.Add("U","110000001");
Decode.Add("V","011000001");
Decode.Add("W","111000000");
Decode.Add("X","010010001");
Decode.Add("Y","110010000");
Decode.Add("Z","011010000");
Decode.Add("-","010000101");
Decode.Add("%","000101010");
Decode.Add("$","010101000");
Decode.Add("*","010010100");
CheckCode=new Hashtable();
CheckCode.Add("0","0");
CheckCode.Add("1","1");
CheckCode.Add("2","2");
CheckCode.Add("3","3");
CheckCode.Add("4","4");
CheckCode.Add("5","5");
CheckCode.Add("6","6");
CheckCode.Add("7","7");
CheckCode.Add("8","8");
CheckCode.Add("9","9");
CheckCode.Add("A","10");
CheckCode.Add("B","11");
CheckCode.Add("C","12");
CheckCode.Add("D","13");
CheckCode.Add("E","14");
CheckCode.Add("F","15");
CheckCode.Add("G","16");
CheckCode.Add("H","17");
CheckCode.Add("I","18");
CheckCode.Add("J","19");
CheckCode.Add("K","20");
CheckCode.Add("L","21");
CheckCode.Add("M","22");
CheckCode.Add("N","23");
CheckCode.Add("O","24");
CheckCode.Add("P","25");
CheckCode.Add("Q","26");
CheckCode.Add("R","27");
CheckCode.Add("S","28");
CheckCode.Add("T","29");
CheckCode.Add("U","30");
CheckCode.Add("V","31");
CheckCode.Add("W","32");
CheckCode.Add("X","33");
CheckCode.Add("Y","34");
CheckCode.Add("Z","35");
CheckCode.Add("-","36");
CheckCode.Add(".","37");
CheckCode.Add(",","38");
CheckCode.Add("$","39");
CheckCode.Add("/","40");
CheckCode.Add("+","41");
CheckCode.Add("%","42");
}
//保存文件
public Boolean saveFile(string Code,string Title,int UseCheck)
{
string code39=Encode39(Code,UseCheck);
if(code39!=null)
{
Bitmap saved=new Bitmap(this.Width,this.Height);
Graphics g=Graphics.FromImage(saved);
g.FillRectangle(new SolidBrush(Color.White),0,0,this.Width,this.Height);
this.DrawBarCode39(code39,Title,g);
//string path=ConfigurationSettings.AppSettings["ImagePath"];
string path="C:\\";
string filename=path+Code+".jpg";
saved.Save(filename,ImageFormat.Jpeg);
saved.Dispose();
return true;
}
return false;
}
/***
* Code:未经编码的字符串
*
* **/
private string Encode39(string Code,int UseCheck)
{
int UseStand = 1; //检查输入待编码字符是否为标准格式(是否以*开始结束)
//保存备份数据
string OriginalCode=Code;
//为空不进行编码
if(null==Code||Code.Trim().Equals(""))
{
return null;
}
//检查错误字符
Code = Code.ToUpper(); //转为大写
Regex rule = new Regex(@"[^0-9A-Z%$\-*]");
if(rule.IsMatch(Code))
{
MessageBox.Show("编码中包含非法字符,目前仅支持字母,数字及%$-*符号!!");
return null;
}
//计算检查码
if (UseCheck==1)
{
int Check = 0;
//累计求和
for (int i = 0; i < Code.Length; i++)
{
Check += int.Parse((string)CheckCode[Code.Substring(i,1)]);
}
//取模
Check=Check%43;
//附加检测码
foreach(DictionaryEntry de in CheckCode)
{
if((string)de.Value==Check.ToString())
{
Code=Code+(string)de.Key;
break;
}
}
}
//标准化输入字符,增加起始标记
if (UseStand==1)
{
if (Code.Substring(0,1) != "*")
{
Code = "*" + Code;
}
if (Code.Substring(Code.Length-1,1)!="*")
{
Code = Code + "*";
}
}
//转换成39编码
string Code39="";
for (int i = 0; i < Code.Length; i++)
{
Code39=Code39+(string)Decode[Code.Substring(i,1)]+SPARATOR;
}
int height = 30+LineHeight;//定义图片高度
int width=xCoordinate;
for(int i=0;i<Code39.Length;i++)
{
if("0".Equals(Code39.Substring(i,1)))
{
width+=WidthXI;
}
else
{
width+=WidthCU;
}
}
this.Width=width+xCoordinate;
this.Height=height;
return Code39;
}
private void DrawBarCode39(string Code39,string Title,Graphics g)
{
int UseTitle = 1; //条码上端显示标题
//int UseTTF = 1; //使用TTF字体,方便显示中文,需要$UseTitle=1时才能生效
if(Title.Trim().Equals(""))
{
UseTitle=0;
}
Pen pWhite=new Pen(Color.White, 1);
Pen pBlack=new Pen(Color.Black, 1);
int position=xCoordinate;
for(int i=0;i<Code39.Length;i++)
{
//绘制条线
if("0".Equals(Code39.Substring(i,1)))
{
for(int j=0;j<WidthXI;j++)
{
g.DrawLine(pBlack,position+j,5,position+j,5+LineHeight);
}
position+=WidthXI;
}
else
{
for(int j=0;j<WidthCU;j++)
{
g.DrawLine(pBlack,position+j,5,position+j,5+LineHeight);
}
position+=WidthCU;
}
i++;
//绘制间隔线
if("0".Equals(Code39.Substring(i,1)))
{
position+=WidthXI;
}
else
{
position+=WidthCU;
}
}
//显示标题
if(UseTitle==1)
{
Font TitleFont=new Font("宋体", 16, FontStyle.Bold);
SizeF sf=g.MeasureString(Title,TitleFont);
g.DrawString(Title,TitleFont, Brushes.Black,(Width-sf.Width)/2,LineHeight+5);
}
return ;
}
}
}