123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /*
- * barcode generator - code128
- */
- var gm = require('gm');
- const BARMAP = [
- [2,1,2,2,2,2], [2,2,2,1,2,2], [2,2,2,2,2,1], [1,2,1,2,2,3], [1,2,1,3,2,2],
- [1,3,1,2,2,2], [1,2,2,2,1,3], [1,2,2,3,1,2], [1,3,2,2,1,2], [2,2,1,2,1,3],
- [2,2,1,3,1,2], [2,3,1,2,1,2], [1,1,2,2,3,2], [1,2,2,1,3,2], [1,2,2,2,3,1],
- [1,1,3,2,2,2], [1,2,3,1,2,2], [1,2,3,2,2,1], [2,2,3,2,1,1], [2,2,1,1,3,2],
- [2,2,1,2,3,1], [2,1,3,2,1,2], [2,2,3,1,1,2], [3,1,2,1,3,1], [3,1,1,2,2,2],
- [3,2,1,1,2,2], [3,2,1,2,2,1], [3,1,2,2,1,2], [3,2,2,1,1,2], [3,2,2,2,1,1],
- [2,1,2,1,2,3], [2,1,2,3,2,1], [2,3,2,1,2,1], [1,1,1,3,2,3], [1,3,1,1,2,3],
- [1,3,1,3,2,1], [1,1,2,3,1,3], [1,3,2,1,1,3], [1,3,2,3,1,1], [2,1,1,3,1,3],
- [2,3,1,1,1,3], [2,3,1,3,1,1], [1,1,2,1,3,3], [1,1,2,3,3,1], [1,3,2,1,3,1],
- [1,1,3,1,2,3], [1,1,3,3,2,1], [1,3,3,1,2,1], [3,1,3,1,2,1], [2,1,1,3,3,1],
- [2,3,1,1,3,1], [2,1,3,1,1,3], [2,1,3,3,1,1], [2,1,3,1,3,1], [3,1,1,1,2,3],
- [3,1,1,3,2,1], [3,3,1,1,2,1], [3,1,2,1,1,3], [3,1,2,3,1,1], [3,3,2,1,1,1],
- [3,1,4,1,1,1], [2,2,1,4,1,1], [4,3,1,1,1,1], [1,1,1,2,2,4], [1,1,1,4,2,2],
- [1,2,1,1,2,4], [1,2,1,4,2,1], [1,4,1,1,2,2], [1,4,1,2,2,1], [1,1,2,2,1,4],
- [1,1,2,4,1,2], [1,2,2,1,1,4], [1,2,2,4,1,1], [1,4,2,1,1,2], [1,4,2,2,1,1],
- [2,4,1,2,1,1], [2,2,1,1,1,4], [4,1,3,1,1,1], [2,4,1,1,1,2], [1,3,4,1,1,1],
- [1,1,1,2,4,2], [1,2,1,1,4,2], [1,2,1,2,4,1], [1,1,4,2,1,2], [1,2,4,1,1,2],
- [1,2,4,2,1,1], [4,1,1,2,1,2], [4,2,1,1,1,2], [4,2,1,2,1,1], [2,1,2,1,4,1],
- [2,1,4,1,2,1], [4,1,2,1,2,1], [1,1,1,1,4,3], [1,1,1,3,4,1], [1,3,1,1,4,1],
- [1,1,4,1,1,3], [1,1,4,3,1,1], [4,1,1,1,1,3], [4,1,1,3,1,1], [1,1,3,1,4,1],
- [1,1,4,1,3,1], [3,1,1,1,4,1], [4,1,1,1,3,1], [2,1,1,4,1,2], [2,1,1,2,1,4],
- [2,1,1,2,3,2], [2,3,3,1,1,1,2], [2,1,1,1,3,3]
- ];
- const CODEMAPS = {
- 'A': [
- ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
- '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
- '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
- '\\', ']', '^', '_', 'NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL',
- 'BS', 'HT', 'LF', 'VT', 'FF', 'CR', 'SO', 'SI', 'DLE', 'DC1', 'DC2', 'DC3',
- 'DC4', 'NAK', 'SYN', 'ETB', 'CAN', 'EM', 'SUB', 'ESC', 'FS', 'GS', 'RS', 'US',
- 'FNC3', 'FNC3', 'SHIFTB', 'CODEC', 'CODEB', 'FNC4', 'FNC1'
- ],
- 'B': [
- ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
- '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
- '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[',
- '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
- 'z', '{', '|', '}', '~', 'DEL', 'FNC3', 'FNC2', 'SHIFTA', 'CODEC', 'FNC4',
- 'CODEA', 'FNC1'
- ],
- 'C': [
- '00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
- '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
- '20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
- '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
- '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
- '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
- '60', '61', '62', '63', '64', '65', '66', '67', '68', '69',
- '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
- '80', '81', '82', '83', '84', '85', '86', '87', '88', '89',
- '90', '91', '92', '93', '94', '95', '96', '97', '98', '99',
- 'CODEB', 'CODEA', 'FNC1',
- ]
- };
- const STARTA = BARMAP[103];
- const STARTB = BARMAP[104];
- const STARTC = BARMAP[105];
- const STOP = BARMAP[106];
- const START = {
- 'A': STARTA,
- 'B': STARTB,
- 'C': STARTC
- };
- function getVal(mode, ch) {
- return i = mode.toUpperCase() in CODEMAPS &&
- CODEMAPS[mode.toUpperCase()].indexOf(ch) ||
- 0;
- }
- module.exports.createCode = function (options, callback) {
- if (!options.data) {
- return callback(new Error('No data given'), {});
- }
- if (!options.w || !options.h) {
- return callback(new Error('Width and Height must be non-zero'), {});
- }
- // @todo refactor ------------------------------------------------------------
- // we want to detect and optimize the best mode switching for the shortest
- // code and the best space utilization.
- var mode = options.mode || 'B';
- // START + CHECK + END + DATA
- var baseWidth = 11 + 11 + 13 + options.data.length * 11;
- var barWidth = options.w / baseWidth >> 0;
- if (!barWidth) {
- return callback(new Error('Width will result in a degenerate barcode'), {});
- }
- // encode
- var encoded = [ START[mode] ];
- var checkSum = (mode == 'A') ? 103 : (mode == 'B' ? 104 : 105);
- for(var i in options.data) {
- i = parseInt(i); // shoudn't i already be a number? It's not.
- var val = getVal(mode, options.data[i] );
- encoded.push( BARMAP[val] );
- checkSum += (i + 1) * val;
- }
- // add on check digit
- encoded.push(BARMAP[ checkSum % 103 ]);
- encoded.push(STOP);
- // @todo end -----------------------------------------------------------------
- var img = gm(options.w, options.h, options.bgcolor),
- count = 0,
- pos = 0,
- w;
- img.stroke(options.barcolor, 1);
- pos = (options.w - baseWidth * barWidth) / 2 >> 0;
- for (var i in encoded) {
- for (var k in encoded[i]) {
- w = encoded[i][k] * barWidth;
- // only draw even indecies
- if ( ! (k % 2) ) {
- for (var m = 0; m < w; m++) {
- img.drawLine(pos + m, 0, pos + m, options.h);
- }
- }
- pos += w;
- }
- }
- img.stream(options.type, function (err, stdout, stderr) {
- callback(err, stdout);
- });
- };
|