Fratozzi Posted March 20, 2020 Share Posted March 20, 2020 (edited) Hi everyone, I'm trying to read a barcode like Code 32 Italian Pharmacological Code, use this function in JS. But I can't, do you know where I'm wrong or do you know some free library to use? Thank you var barcode = function() { var localMediaStream = null; var bars = []; var handler = null; var dimensions = { height: 0, width: 0, start: 0, end: 0 } var elements = { video: null, canvas: null, ctx: null, canvasg: null, ctxg: null } var upc = { '0': [3, 2, 1, 1], '1': [2, 2, 2, 1], '2': [2, 1, 2, 2], '3': [1, 4, 1, 1], '4': [1, 1, 3, 2], '5': [1, 2, 3, 1], '6': [1, 1, 1, 4], '7': [1, 3, 1, 2], '8': [1, 2, 1, 3], '9': [3, 1, 1, 2] }; var check = { 'oooooo': '0', 'ooeoee': '1', 'ooeeoe': '2', 'ooeeeo': '3', 'oeooee': '4', 'oeeooe': '5', 'oeeeoo': '6', 'oeoeoe': '7', 'oeoeeo': '8', 'oeeoeo': '9' } var config = { strokeColor: '#f00', start: 0.1, end: 0.9, threshold: 160, quality: 0.45, delay: 100, video: '', canvas: '', canvasg: '' } function init() { window.URL = window.URL || window.webkitURL; navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia; elements.video = document.querySelector(config.video); elements.canvas = document.querySelector(config.canvas); elements.ctx = elements.canvas.getContext('2d'); elements.canvasg = document.querySelector(config.canvasg); elements.ctxg = elements.canvasg.getContext('2d'); if (navigator.getUserMedia) { navigator.getUserMedia({audio: false, video: true}, function(stream) { elements.video.srcObject = stream; }); } elements.video.addEventListener('canplay', function(e) { dimensions.height = elements.video.videoHeight; dimensions.width = elements.video.videoWidth; dimensions.start = dimensions.width * config.start; dimensions.end = dimensions.width * config.end; elements.canvas.width = dimensions.width; elements.canvas.height = dimensions.height; elements.canvasg.width = dimensions.width; elements.canvasg.height = dimensions.height; drawGraphics(); setInterval(function(){snapshot()}, config.delay); }, false); } function snapshot() { elements.ctx.drawImage(elements.video, 0, 0, dimensions.width, dimensions.height); processImage(); } function processImage() { bars = []; var pixels = []; var binary = []; var pixelBars = []; // convert to grayscale var imgd = elements.ctx.getImageData(dimensions.start, dimensions.height * 0.5, dimensions.end - dimensions.start, 1); var rgbpixels = imgd.data; for (var i = 0, ii = rgbpixels.length; i < ii; i = i + 4) { pixels.push(Math.round(rgbpixels * 0.2126 + rgbpixels[i + 1] * 0.7152 + rgbpixels[ i + 2] * 0.0722)); } // normalize and convert to binary var min = Math.min.apply(null, pixels); var max = Math.max.apply(null, pixels); for (var i = 0, ii = pixels.length; i < ii; i++) { if (Math.round((pixels - min) / (max - min) * 255) > config.threshold) { binary.push(1); } else { binary.push(0); } } // determine bar widths var current = binary[0]; var count = 0; for (var i = 0, ii = binary.length; i < ii; i++) { if (binary == current) { count++; } else { pixelBars.push(count); count = 1; current = binary } } pixelBars.push(count); // quality check if (pixelBars.length < (3 + 24 + 5 + 24 + 3 + 1)) { return; } // find starting sequence var startIndex = 0; var minFactor = 0.5; var maxFactor = 1.5; for (var i = 3, ii = pixelBars.length; i < ii; i++) { var refLength = (pixelBars + pixelBars[i-1] + pixelBars[i-2]) / 3; if ( (pixelBars > (minFactor * refLength) || pixelBars < (maxFactor * refLength)) && (pixelBars[i-1] > (minFactor * refLength) || pixelBars[i-1] < (maxFactor * refLength)) && (pixelBars[i-2] > (minFactor * refLength) || pixelBars[i-2] < (maxFactor * refLength)) && (pixelBars[i-3] > 3 * refLength) ) { startIndex = i - 2; break; } } // return if no starting sequence found if (startIndex == 0) { return; } // discard leading and trailing patterns pixelBars = pixelBars.slice(startIndex, startIndex + 3 + 24 + 5 + 24 + 3); // calculate relative widths var ref = (pixelBars[0] + pixelBars[1] + pixelBars[2]) / 3; for (var i = 0, ii = pixelBars.length; i < ii; i++) { bars.push(Math.round(pixelBars / ref * 100) / 100); } // analyze pattern analyze(); } function analyze() { // determine parity first digit and reverse sequence if necessary var first = normalize(bars.slice(3, 3 + 4), 7); if (!isOdd(Math.round(first[1] + first[3]))) { bars = bars.reverse(); } // split into digits var digits = [ normalize(bars.slice(3, 3 + 4), 7), normalize(bars.slice(7, 7 + 4), 7), normalize(bars.slice(11, 11 + 4), 7), normalize(bars.slice(15, 15 + 4), 7), normalize(bars.slice(19, 19 + 4), 7), normalize(bars.slice(23, 23 + 4), 7), normalize(bars.slice(32, 32 + 4), 7), normalize(bars.slice(36, 36 + 4), 7), normalize(bars.slice(40, 40 + 4), 7), normalize(bars.slice(44, 44 + 4), 7), normalize(bars.slice(48, 48 + 4), 7), normalize(bars.slice(52, 52 + 4), 7) ] // determine parity and reverse if necessary var parities = []; for (var i = 0; i < 6; i++) { if (parity(digits)) { parities.push('o'); } else { parities.push('e'); digits = digits.reverse(); } } // identify digits var result = []; var quality = 0; for (var i = 0, ii = digits.length; i < ii; i++) { var distance = 9; var bestKey = ''; for (key in upc) { if (maxDistance(digits, upc[key]) < distance) { distance = maxDistance(digits, upc[key]); bestKey = key; } } result.push(bestKey); if (distance > quality) { quality = distance; } } // check digit var checkDigit = check[parities.join('')]; // output if(quality < config.quality) { if (handler != null) { handler(checkDigit + result.join('')); } } } function setHandler(h) { handler = h; } function normalize(input, total) { var sum = 0; var result = []; for (var i = 0, ii = input.length; i < ii; i++) { sum = sum + input; } for (var i = 0, ii = input.length; i < ii; i++) { result.push(input / sum * total); } return result; } function isOdd(num) { return num % 2; } function maxDistance(a, b) { var distance = 0; for (var i = 0, ii = a.length; i < ii; i++) { if (Math.abs(a - b) > distance) { distance = Math.abs(a - b); } } return distance; } function parity(digit) { return isOdd(Math.round(digit[1] + digit[3])); } function drawGraphics() { elements.ctxg.strokeStyle = config.strokeColor; elements.ctxg.lineWidth = 3; elements.ctxg.beginPath(); elements.ctxg.moveTo(dimensions.start, dimensions.height * 0.5); elements.ctxg.lineTo(dimensions.end, dimensions.height * 0.5); elements.ctxg.stroke(); } return { init: init, setHandler: setHandler, config: config }; // debugging utilities function drawBars(binary) { for (var i = 0, ii = binary.length; i < ii; i++) { if (binary == 1) { elements.ctxg.strokeStyle = '#fff'; } else { elements.ctxg.strokeStyle = '#000'; } elements.ctxg.lineWidth = 3; elements.ctxg.beginPath(); elements.ctxg.moveTo(start + i, height * 0.5); elements.ctxg.lineTo(start + i + 1, height * 0.5); elements.ctxg.stroke(); } } }(); Edited March 20, 2020 by requinix please use the Code <> button when posting code. Quote Link to comment https://forums.phpfreaks.com/topic/310333-barcode-code-32-italian-pharmacode-js/ Share on other sites More sharing options...
requinix Posted March 20, 2020 Share Posted March 20, 2020 I don't know what's wrong with that code because you haven't described the sort of problem you're having with it. I don't see any library that explicitly mentions supporting Code 32, but it appears to be somewhat compatible with Code 39. You may be able to get a library to read those (which are much more common), and then convert the encoded value to Code 32 using an algorithm I don't know. Quote Link to comment https://forums.phpfreaks.com/topic/310333-barcode-code-32-italian-pharmacode-js/#findComment-1575639 Share on other sites More sharing options...
Fratozzi Posted April 10, 2020 Author Share Posted April 10, 2020 On 3/20/2020 at 3:33 PM, requinix said: I don't know what's wrong with that code because you haven't described the sort of problem you're having with it. I don't see any library that explicitly mentions supporting Code 32, but it appears to be somewhat compatible with Code 39. You may be able to get a library to read those (which are much more common), and then convert the encoded value to Code 32 using an algorithm I don't know. I searched the internet and found this library (https://github.com/ericblade/quagga2) that is right for me. Now I would like to be able to implement code 32, I read on the internet that the conversion is the same as code 39 (already existing in the library), I created this file and added it to the list of barcodes to use, but it doesn't work, I also found this on the internet for coding ... can you tell me where am i wrong? file created by me : code_32.js import BarcodeReader from './barcode_reader'; import ArrayHelper from '../common/array_helper.ts'; function Code32Reader() { BarcodeReader.call(this); } var properties = { ALPHABETH_STRING: {value: '0123456789BCDFGHJKLMNPQRSTUVWXYZ*'}, ALPHABET: {value: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 66, 67, 68, 70, 71, 72, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 42]}, CHARACTER_ENCODINGS: {value: [0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x049, 0x148, 0x019, 0x058, 0x00D, 0x10C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x094, ]}, ASTERISK: {value: 0x094}, FORMAT: {value: 'code_32', writeable: false}, }; Code32Reader.prototype = Object.create(BarcodeReader.prototype, properties); Code32Reader.prototype.constructor = Code32Reader; Code32Reader.prototype._decode = function() { var self = this, counters = [0, 0, 0, 0, 0, 0, 0, 0, 0], result = [], start = self._findStart(), decodedChar, lastStart, pattern, nextStart; if (!start) { return null; } nextStart = self._nextSet(self._row, start.end); do { counters = self._toCounters(nextStart, counters); pattern = self._toPattern(counters); if (pattern < 0) { return null; } decodedChar = self._patternToChar(pattern); if (decodedChar < 0){ return null; } result.push(decodedChar); lastStart = nextStart; nextStart += ArrayHelper.sum(counters); nextStart = self._nextSet(self._row, nextStart); } while (decodedChar !== '*'); result.pop(); if (!result.length) { return null; } if (!self._verifyTrailingWhitespace(lastStart, nextStart, counters)) { return null; } return { code: result.join(''), start: start.start, end: nextStart, startInfo: start, decodedCodes: result, }; }; Code32Reader.prototype._verifyTrailingWhitespace = function(lastStart, nextStart, counters) { var trailingWhitespaceEnd, patternSize = ArrayHelper.sum(counters); trailingWhitespaceEnd = nextStart - lastStart - patternSize; if ((trailingWhitespaceEnd * 3) >= patternSize) { return true; } return false; }; Code32Reader.prototype._patternToChar = function(pattern) { var i, self = this; for (i = 0; i < self.CHARACTER_ENCODINGS.length; i++) { if (self.CHARACTER_ENCODINGS[i] === pattern) { return String.fromCharCode(self.ALPHABET[i]); } } return -1; }; Code32Reader.prototype._findNextWidth = function(counters, current) { var i, minWidth = Number.MAX_VALUE; for (i = 0; i < counters.length; i++) { if (counters[i] < minWidth && counters[i] > current) { minWidth = counters[i]; } } return minWidth; }; Code32Reader.prototype._toPattern = function(counters) { var numCounters = counters.length, maxNarrowWidth = 0, numWideBars = numCounters, wideBarWidth = 0, self = this, pattern, i; while (numWideBars > 3) { maxNarrowWidth = self._findNextWidth(counters, maxNarrowWidth); numWideBars = 0; pattern = 0; for (i = 0; i < numCounters; i++) { if (counters[i] > maxNarrowWidth) { pattern |= 1 << (numCounters - 1 - i); numWideBars++; wideBarWidth += counters[i]; } } if (numWideBars === 3) { for (i = 0; i < numCounters && numWideBars > 0; i++) { if (counters[i] > maxNarrowWidth) { numWideBars--; if ((counters[i] * 2) >= wideBarWidth) { return -1; } } } return pattern; } } return -1; }; Code32Reader.prototype._findStart = function() { var self = this, offset = self._nextSet(self._row), patternStart = offset, counter = [0, 0, 0, 0, 0, 0, 0, 0, 0], counterPos = 0, isWhite = false, i, j, whiteSpaceMustStart; for ( i = offset; i < self._row.length; i++) { if (self._row[i] ^ isWhite) { counter[counterPos]++; } else { if (counterPos === counter.length - 1) { // find start pattern if (self._toPattern(counter) === self.ASTERISK) { whiteSpaceMustStart = Math.floor(Math.max(0, patternStart - ((i - patternStart) / 4))); if (self._matchRange(whiteSpaceMustStart, patternStart, 0)) { return { start: patternStart, end: i, }; } } patternStart += counter[0] + counter[1]; for ( j = 0; j < 7; j++) { counter[j] = counter[j + 2]; } counter[7] = 0; counter[8] = 0; counterPos--; } else { counterPos++; } counter[counterPos] = 1; isWhite = !isWhite; } } return null; }; export default Code32Reader; Conversion method (Found online): ` Conversion from CODE 39 ` to Italian Farmaceutical Code ` for bar code reader ` whithout automatic conversion ` R.V. 29/07/2000 C_TEXT($1;$0) C_REAL($result) C_INTEGER($len;$base10;$base32) $result:=0 $len:=Length($1) For ($X;1;$len) $char:=($1<=($len-$X+1)>=) $base32:=Ascii($char) $base10:=$base32-(48+(8*Num($base32>65))+*Num($base32>69)+*Num($base32>73)+*Num($base32>79)) $result:=$result+($base10*(32^($X-1))) End for $0:=String($result) $0:=("0"*Num(Length($0)=8))+$0 ` Conversion from CODE 39 ` to CODE 32 Farmacod ` (Italian farmaceutical code) ` R.V. 29/07/2002 C_TEXT($1;$0) C_REAL($value) C_INTEGER($X;$codASCII) C_LONGINT($base32) $value:=Num($1) $0:="" For ($X;1;6) $base32:=$value-(Int($value/32)*32) $codASCII:=$base32+48+((8*Num($base32>9))+Num($base32>12)+Num($base32>15)+Num($base32>20)) $0:=Char($codASCII)+$0 $value:=Int($value/32) End for Characters exclude A, E, I, O Quote Link to comment https://forums.phpfreaks.com/topic/310333-barcode-code-32-italian-pharmacode-js/#findComment-1576638 Share on other sites More sharing options...
requinix Posted April 10, 2020 Share Posted April 10, 2020 For me to have any chance of telling you what's wrong, you're going to have to describe what "doesn't work" means. It's not like I'm there watching over your shoulder as you try to run it. Quote Link to comment https://forums.phpfreaks.com/topic/310333-barcode-code-32-italian-pharmacode-js/#findComment-1576644 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.