12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- /*
- * barcode generator - UPC-A
- */
- var gm = require('gm'),
- getCheckDigit = require('./utils/checksums').weight3odd10,
- Barcode1D = require('./utils/draw1D');
- const START = [1,1,1];
- const MIDDLE = [1,1,1,1,1];
- const END = [1,1,1];
- const BARMAP = [
- [3,2,1,1], [2,2,2,1], [2,1,2,2], [1,4,1,1], [1,1,3,2],
- [1,2,3,1], [1,1,1,4], [1,3,1,2], [1,2,1,3], [3,1,1,2]
- ];
- /*
- This is because UPC always has the same formula:
- Start - 3 wide
- Data (x6) - 7 wide
- Middle - 5 wide)
- Data (x5) - 7 wide
- Check - 7 wide
- End - 3 wide
- */
- const MODULE_WIDTH = 95;
- const FULL_DATA_LEN = 12
- const REG_DATA_LEN = 11;
- module.exports.createCode = function (options, callback) {
- if (!options.data) {
- return callback(new Error('No data given'), {});
- }
- var userCheckDigit = false;
- options.data = ('' + options.data).replace(/[^0-9]/g, ''); // force to string
- if (options.data.length === FULL_DATA_LEN) {
- userCheckDigit = parseInt(options.data.substr(-1));
- options.data = options.data.substr(0, REG_DATA_LEN)
- }
- else if (options.data.length !== REG_DATA_LEN) {
- return callback(new Error('Data must be 11 digits (0-9) long for UPC-A'), {});
- }
- if (!options.w || !options.h) {
- return callback(new Error('Width and Height must be non-zero'), {});
- }
- var barWidth = options.w / MODULE_WIDTH >> 0;
- if (!barWidth) {
- return callback(new Error('Width will result in a degenerate barcode'), {});
- }
- // @todo externalize this to a function that generates the sequence
- var digit, encoding = [START];
- for (var i = 0; i < options.data.length; i++) {
- // Between position 6 and 7
- if (i == 6) {
- encoding.push(MIDDLE);
- }
- digit = parseInt(options.data[i]);
- encoding.push( BARMAP[ digit ] );
- }
- var checkDigit = getCheckDigit(options.data);
- // we're doing them a service by verifying it for them, the UPC wont work
- // otherwise, and they might have bad data.
- if (userCheckDigit !== false && checkDigit !== userCheckDigit) {
- return callback(new Error('Supplied check digit (digit 12: ' +
- userCheckDigit + ') is incorrect. Correct: ' + checkDigit), {} );
- }
- encoding.push(BARMAP[checkDigit]);
- encoding.push(END);
- // @todo make pattern generation function that ouputs a flat array instead
- // of a 2d array with each digit separate
- var flatPattern = [];
- for(var i=0; i<encoding.length; ++i) {
- flatPattern = flatPattern.concat(encoding[i]);
- }
- new Barcode1D().setWidth(options.w)
- .setHeight(options.h)
- .setModuleWidth(MODULE_WIDTH)
- .draw(flatPattern, callback);
- }
|