条形码二维码由于规则简单,读取效率,在目前人们生活中应用广泛。一般情况下,不必了解原理,就可以借助ZXING和BARCODE,ZBAR等各种开发库实现。在某些特殊场合或者特别要求的场合下,比如发明一种特殊的条形码,比如改进编码规则,比如对特别识别过程优化等情况。CODE128应用十分广泛,这里从CODE128的编码规则并从规则出发开发相应的二维码生成和识别程序来抛砖引玉。
CODE128简介
CODE128 码于 1981 年推出,是一种长度可变、连续性的字母数字条码。与其他一维条码比 较起来,相对较为复杂,支持的宇元也相对较多,又有不同的编码为式可供交互运用,因此其应 用弹性也较大。CODE 128 特性
1、具有 A、 B、 C 三种不同的编码类型,可提供标准 ASC II中 128 个宇元的编码使用; 2、允许双向扫描;
3、可自行决定是否加上校验位;
4、条码长度可调,但包括开始位和结束位在内,不可超过 232 个字元;
5、同一个 CODE128 码可以由 A、 B、 C 三种不同编码规则互换,既可扩大字元选择的范围, 也可缩短编码的长度。CODE 128 编码方式的编码范围
1、 CODE128A:标准数字、大写字母、控制符及特殊宇符;
2、 CODE128B:标准数字、大写宇母、小写字母及特殊字符;
3、 CODE128C/EAN128: [ 00]~[ 99]的数字对集合,共 100 个,既只能表示偶数位长 度的数字。CODE 128 编码规则
开始位+[ FNC1(为 EAN128 码时附加)]+数据位+校验位+结束位
CODE128 校验位计算
(开始位对应 ID+每位数据在整个数据中的位置×每位数据对应的 ID 值) % 103CODE 128 编码表如下,
横向依次对应索引ID, ABC三种编码字符,BANDCODE和二进制编码表,纵向对支持的字符,C码只支持数字,B码支持数字,字母和特殊字符,A码支持数字,字母,特殊字符和控制字符
A B C A B C 00 SP SP 00 11011001100 01 ! ! 01 11001101100 02 " " 02 11001100110 03 # # 03 10010011000 04 $ $ 04 10010001100 05 % % 05 10001001100 06 & & 06 10011001000 07 /' /' 07 10011000100 08 ( ( 08 10001100100 09 ) ) 09 11001001000 10 * * 10 11001000100 11 + + 11 11000100100 12 , , 12 10110011100 13 - - 13 10011011100 14 . . 14 10011001110 15 / / 15 10111001100 16 0 0 16 10011101100 17 1 1 17 10011100110 18 2 2 18 11001110010 19 3 3 19 11001011100 20 4 4 20 11001001110 21 5 5 21 11011100100 22 6 6 22 11001110100 23 7 7 23 11101101110 24 8 8 24 11101001100 25 9 9 25 11100101100 26 : : 26 11100100110 27 ; ; 27 11101100100 28 < < 28 11100110100 29 = = 29 11100110010 30 > > 30 11011011000 31 ? ? 31 11011000110 32 @ @ 32 11000110110 33 A A 33 10100011000 34 B B 34 10001011000 35 C C 35 10001000110 36 D D 36 10110001000 37 E E 37 10001101000 38 F F 38 10001100010 39 G G 39 11010001000 40 H H 40 11000101000 41 I I 41 11000100010 42 J J 42 10110111000 43 K K 43 10110001110 44 L L 44 10001101110 45 M M 45 10111011000 46 N N 46 10111000110 47 O O 47 10001110110 48 P P 48 11101110110 49 Q Q 49 11010001110 50 R R 50 11000101110 51 S S 51 11011101000 52 T T 52 11011100010 53 U U 53 1101110111054 V V 54 1110101100055 W W 55 11101000110 56 X X 56 1110001011057 Y Y 57 1110110100058 Z Z 58 1110110001059 [ [ 59 1110001101060 // // 60 1110111101061 ] ] 61 1100100001062 ^ ^ 62 1111000101063 _ _ 63 1010011000064 NUL ` 64 1010000110065 SOH a 65 1001011000066 STX b 66 1001000011067 ETX c 67 1000010110068 EOT d 68 1000010011069 ENQ e 69 1011001000070 ACK f 70 1011000010071 BEL g 71 1001101000072 BS h 72 1001100001073 HT I 73 1000011010074 LF j 74 1000011001075 VT k 75 1100001001076 FF l 76 1100101000076 FF l 76 1100101000077 CR m 77 1111011101078 SO n 78 1100001010079 SI o 79 1000111101080 DLE p 80 1010011110081 DC1 q 81 1001011110082 DC2 r 82 1001001111083 DC3 s 83 1011110010084 DC4 t 84 1001111010085 NAK u 85 1001111001086 SYN v 86 1111010010087 ETB w 87 1111001010088 CAN x 88 1111001001089 EM y 89 1101101111090 SUB z 90 1101111011091 ESC { 91 1111011011092 FS | 92 1010111100093 GS } 93 1010001111094 RS ~ 94 1000101111095 US DEL 95 1011110100096 FNC3 FNC3 96 1011110001097 FNC2 FNC2 97 1111010100098 SHIFT SHIFT 98 1111010001099 CodeC CodeC 99 10111011110100 CodeB FNC4 CodeB 10111101110101 FNC4 CodeA CodeA 11101011110 102 FNC1 FNC1 FNC1 11110101110 103 STARTA STARTA STARTA 11010000100104 STARTB STARTB STARTB 11010010000105 STARTC STARTC STARTC 11010011100终止符 STOP STOP STOP 1100011101011
编程实现,创建一个二维数组表,把编码表存入,数组第0列A码,第1列B码,第2列C码,第3列bandcode,第4列对就二进制编码值,整体算法十分简单,把要编码的内容读入,按照下表转为二进制编码值,生成数据位,最后按照规则,开始位+[FNC1(为 EAN128 码时附加)]+数据位+校验位+结束位组合成完整二进制编码数据,最后调用平台GUI函数按照合成的完整二进制码,1对应白色竖线,0对应黑色竖线绘制出来,线高和线宽可以根据需要调整,下面给出完整的JAVA代码和android代码,java绘图使用AWT图形库。
public class TestCode128C { String[][] code128 = { { " ", " ", "00", "212222", "11011001100" }, { "!", "!", "01", "222122", "11001101100" }, { "\"", "\"", "02", "222221", "11001100110" }, { "#", "#", "03", "121223", "10010011000" }, { "$", "$", "04", "121322", "10010001100" }, { "%", "%", "05", "131222", "10001001100" }, { "&", "&", "06", "122213", "10011001000" }, { "'", "'", "07", "122312", "10011000100", }, { "(", "(", "08", "132212", "10001100100" }, { ")", ")", "09", "221213", "11001001000" }, { "*", "*", "10", "221312", "11001000100" }, { "+", "+", "11", "231212", "11000100100" }, { ",", ",", "12", "112232", "10110011100" }, { "-", "-", "13", "122132", "10011011100" }, { ".", ".", "14", "122231", "10011001110" }, { "/", "/", "15", "113222", "10111001100" }, { "0", "0", "16", "123122", "10011101100" }, { "1", "1", "17", "123221", "10011100110" }, { "2", "2", "18", "223211", "11001110010", }, { "3", "3", "19", "221132", "11001011100" }, { "4", "4", "20", "221231", "11001001110", }, { "5", "5", "21", "213212", "11011100100" }, { "6", "6", "22", "223112", "11001110100" }, { "7", "7", "23", "312131", "11101101110" }, { "8", "8", "24", "311222", "11101001100" }, { "9", "9", "25", "321122", "11100101100" }, { ":", ":", "26", "321221", "11100100110" }, { ";", ";", "27", "312212", "11101100100" }, { "<", "<", "28", "322112", "11100110100" }, { "=", "=", "29", "322211", "11100110010" }, { ">", ">", "30", "212123", "11011011000" }, { "?", "?", "31", "212321", "11011000110" }, { "@", "@", "32", "232121", "11000110110" }, { "A", "A", "33", "111323", "10100011000" }, { "B", "B", "34", "131123", "10001011000" }, { "C", "C", "35", "131321", "10001000110" }, { "D", "D", "36", "112313", "10110001000" }, { "E", "E", "37", "132113", "10001101000" }, { "F", "F", "38", "132311", "10001100010" }, { "G", "G", "39", "211313", "11010001000" }, { "H", "H", "40", "231113", "11000101000" }, { "I", "I", "41", "231311", "11000100010" }, { "J", "J", "42", "112133", "10110111000" }, { "K", "K", "43", "112331", "10110001110" }, { "L", "L", "44", "132131", "10001101110" }, { "M", "M", "45", "113123", "10111011000" }, { "N", "N", "46", "113321", "10111000110" }, { "O", "O", "47", "133121", "10001110110" }, { "P", "P", "48", "313121", "11101110110" }, { "Q", "Q", "49", "211331", "11010001110" }, { "R", "R", "50", "231131", "11000101110" }, { "S", "S", "51", "213113", "11011101000" }, { "T", "T", "52", "213311", "11011100010" }, { "U", "U", "53", "213131", "11011101110" }, { "V", "V", "54", "311123", "11101011000" }, { "W", "W", "55", "311321", "11101000110" }, { "X", "X", "56", "331121", "11100010110" }, { "Y", "Y", "57", "312113", "11101101000" }, { "Z", "Z", "58", "312311", "11101100010" }, { "[", "[", "59", "332111", "11100011010" }, { "\\", "\\", "60", "314111", "11101111010" }, { "]", "]", "61", "221411", "11001000010" }, { "^", "^", "62", "431111", "11110001010" }, { "_", "_", "63", "111224", "10100110000" }, { "NUL", "`", "64", "111422", "10100001100" }, { "SOH", "a", "65", "121124", "10010110000" }, { "STX", "b", "66", "121421", "10010000110" }, { "ETX", "c", "67", "141122", "10000101100" }, { "EOT", "d", "68", "141221", "10000100110" }, { "ENQ", "e", "69", "112214", "10110010000" }, { "ACK", "f", "70", "112412", "10110000100" }, { "BEL", "g", "71", "122114", "10011010000" }, { "BS", "h", "72", "122411", "10011000010" }, { "HT", "i", "73", "142112", "10000110100" }, { "LF", "j", "74", "142211", "10000110010" }, { "VT", "k", "75", "241211", "11000010010" }, { "FF", "I", "76", "221114", "11001010000" }, { "CR", "m", "77", "413111", "11110111010" }, { "SO", "n", "78", "241112", "11000010100" }, { "SI", "o", "79", "134111", "10001111010" }, { "DLE", "p", "80", "111242", "10100111100" }, { "DC1", "q", "81", "121142", "10010111100" }, { "DC2", "r", "82", "121241", "10010011110" }, { "DC3", "s", "83", "114212", "10111100100" }, { "DC4", "t", "84", "124112", "10011110100" }, { "NAK", "u", "85", "124211", "10011110010" }, { "SYN", "v", "86", "411212", "11110100100" }, { "ETB", "w", "87", "421112", "11110010100" }, { "CAN", "x", "88", "421211", "11110010010" }, { "EM", "y", "89", "212141", "11011011110" }, { "SUB", "z", "90", "214121", "11011110110" }, { "ESC", "{", "91", "412121", "11110110110" }, { "FS", "|", "92", "111143", "10101111000" }, { "GS", "},", "93", "111341", "10100011110" }, { "RS", "~", "94", "131141", "10001011110" }, { "US", "DEL", "95", "114113", "10111101000" }, { "FNC3", "FNC3", "96", "114311", "10111100010" }, { "FNC2", "FNC2", "97", "411113", "11110101000" }, { "SHIFT", "SHIFT", "98", "411311", "11110100010" }, { "CODEC", "CODEC", "99", "113141", "10111011110" }, { "CODEB", "FNC4", "CODEB", "114131", "10111101110" }, { "FNC4", "CODEA", "CODEA", "311141", "11101011110" }, { "FNC1", "FNC1", "FNC1", "411131", "11110101110" }, { "StartA", "StartA", "StartA", "211412", "11010000100" }, { "StartB", "StartB", "StartB", "211214", "11010010000" }, { "StartC", "StartC", "StartC", "211232", "11010011100" }, { "Stop", "Stop", "Stop", "2331112", "1100011101011" }, }; /** * 生产Code128的条形码的code * * @param barCode * @param encode * @return */ public String getCode(String barCode, String encode) { String _Text = "";// 返回的参数 List<Integer> _TextNumb = new ArrayList<Integer>();// 2截取位的组合 int _Examine = 105; // 首位 // 编码不能是奇数 if (!((barCode.length() & 1) == 0)) return ""; while (barCode.length() != 0) { int _Temp = 0; try { // Code128 编码必须为数字 _Temp = Integer.valueOf(barCode.substring(0, 2)); } catch (Exception e) { e.printStackTrace(); return ""; } // 获得条纹 _Text += getValue(barCode, barCode.substring(0, 2), _Temp); _TextNumb.add(_Temp); // 条码截取2个就需要去掉用过的前二位 barCode = barCode.substring(2); } if (_TextNumb.size() == 0) { return ""; } _Text = getValue(_Examine) + _Text; // 获取开始位 for (int i = 0; i != _TextNumb.size(); i++) { _Examine += _TextNumb.get(i) * (i + 1); } _Examine = _Examine % 103; // 获得校验位 _Text += getValue(_Examine); // 获取校验位 _Text += "1100011101011"; // 结束位 return _Text; } /** * 根据编号获得条纹 * * @param encode * @param p_Value * @param p_SetID * @return */ private String getValue(String encode, String p_Value, int p_SetID) { return code128[p_SetID][4]; } // / <summary> // / 根据编号获得条纹 // / </summary> // / <param name="p_CodeId"></param> // / <returns></returns> private String getValue(int p_CodeId) { return code128[p_CodeId][4]; } private int m_nImageHeight = 40; // 条码的高度像素数 public static void main(String[] args) throws Exception { TestCode128C c = new TestCode128C(); String barCode = c.getCode("118842807789", ""); c.kiCode128C(barCode, 500, "D:/code128C.jpg"); } // / <summary> // / 生成条码 // / </summary> // / <param name="BarString">条码模式字符串</param> // / <param name="Height">生成的条码高度</param> // / <returns>条码图形</returns> public void kiCode128C(String barString, int Height, String path) { try { //File myPNG = new File(path); m_nImageHeight = Height; OutputStream out = new FileOutputStream(path); if (null == barString || null == out || 0 == barString.length()) return; int nImageWidth = 0; char[] cs = barString.toCharArray(); for (int i = 0; i != cs.length; i++) { nImageWidth = cs.length*10; } BufferedImage bi = new BufferedImage(nImageWidth, m_nImageHeight, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics(); for (int i = 0; i < cs.length; i++) { if ("1".equals(cs[i] + "")) { g.setColor(Color.BLACK); g.fillRect(i*10, 0, 10, m_nImageHeight); } else { g.setColor(Color.WHITE); g.fillRect(i*10, 0, 10, m_nImageHeight); } } //JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); //encoder.encode(bi); ImageIO.write(bi, "jpg", out); out.close(); } catch (Exception e) { e.printStackTrace(); } } } 在android上绘出条形码供机器自动化使用 public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } public MyView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); String barCode = Code128C.getCode("118842807789", ""); int m_nImageHeight = 100; char[] cs = barCode.toCharArray(); Paint p = new Paint(); for (int i = 0; i < cs.length; i++) { if ("1".equals(cs[i] + "")) { //g.setColor(Color.BLACK); //g.fillRect(i, 0, 1, m_nImageHeight); p.setColor(Color.BLACK); //canvas.drawRect(i*10, 0, i*10+10, m_nImageHeight, p); } else { //g.setColor(Color.WHITE); //g.fillRect(i, 0, 1, m_nImageHeight); p.setColor(Color.WHITE); //canvas.drawRect(i*10, 0, i*10+10, m_nImageHeight, p); } canvas.drawRect(i*10, 0, i*10+10, m_nImageHeight, p); } } }