javascript-barcode-reader
Version:
Simple & Fast Barcode decoder for Browser and Node.js
513 lines (497 loc) • 5.56 kB
text/typescript
const WIDTH_TBL = [
'212222',
'222122',
'222221',
'121223',
'121322',
'131222',
'122213',
'122312',
'132212',
'221213',
'221312',
'231212',
'112232',
'122132',
'122231',
'113222',
'123122',
'123221',
'223211',
'221132',
'221231',
'213212',
'223112',
'312131',
'311222',
'321122',
'321221',
'312212',
'322112',
'322211',
'212123',
'212321',
'232121',
'111323',
'131123',
'131321',
'112313',
'132113',
'132311',
'211313',
'231113',
'231311',
'112133',
'112331',
'132131',
'113123',
'113321',
'133121',
'313121',
'211331',
'231131',
'213113',
'213311',
'213131',
'311123',
'311321',
'331121',
'312113',
'312311',
'332111',
'314111',
'221411',
'431111',
'111224',
'111422',
'121124',
'121421',
'141122',
'141221',
'112214',
'112412',
'122114',
'122411',
'142112',
'142211',
'241211',
'221114',
'413111',
'241112',
'134111',
'111242',
'121142',
'121241',
'114212',
'124112',
'124211',
'411212',
'421112',
'421211',
'212141',
'214121',
'412121',
'111143',
'111341',
'131141',
'114113',
'114311',
'411113',
'411311',
'113141',
'114131',
'311141',
'411131',
'211412',
'211214',
'211232',
'233111',
'211133',
'2331112',
]
const TBL_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',
'FNC 3',
'FNC 2',
'Shift B',
'Code C',
'Code B',
'FNC 4',
'FNC 1',
'Code A',
'Code B',
'Code C',
'Stop',
'Reverse Stop',
]
const TBL_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',
'FNC 3',
'FNC 2',
'Shift A',
'Code C',
'FNC 4',
'Code A',
'FNC 1',
'Code A',
'Code B',
'Code C',
'Stop',
'Reverse Stop',
]
const TBL_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',
'Code B',
'Code A',
'FNC 1',
'Code A',
'Code B',
'Code C',
'Stop',
'Reverse Stop',
]
const computeGroup = (lines: number[]): number[] => {
const count = lines.length - 13
const factor =
lines.reduce((pre, item, i) => {
if (i >= count) return pre
return pre + item
}, 0) /
(Math.ceil(count / 6) * 11)
return lines.map(item => Math.round(item / factor) || 1)
}
export function decoder(lines: number[]): string {
const code = []
let lookupTBL = TBL_B
// let sumOP = 0
let letterKey
let letterCodePrev
const computedLines = computeGroup(lines)
if (!computedLines) return ''
// extract terminal bar
computedLines.pop()
// skip check code and stop code using -13
for (let i = 0; i * 6 < computedLines.length - 13; i += 1) {
letterKey = computedLines.slice(i * 6, (i + 1) * 6).join('')
const keyIndex = WIDTH_TBL.indexOf(letterKey)
const letterCode = lookupTBL[keyIndex]
// sumOP += i * keyIndex
switch (letterCode) {
case 'Code A':
lookupTBL = TBL_A
break
case 'Code B':
lookupTBL = TBL_B
break
case 'Code C':
lookupTBL = TBL_C
break
case 'FNC 4':
break
default:
if (letterCode) {
if (letterCodePrev === 'FNC 4') {
code.push(letterCode.charCodeAt(0) + 128)
} else {
code.push(letterCode)
}
letterCodePrev = letterCode
} else {
code.push('?')
}
break
}
}
// letterKey = computedLines.slice(0, 6).join('')
// if (sumOP % 103 !== WIDTH_TBL.indexOf(letterKey)) return ''
return code.join('')
}