Jump to content

Barcode Code 32 (Italian Pharmacode) - JS


Fratozzi

Recommended Posts

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 by requinix
please use the Code <> button when posting code.
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 3 weeks later...
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

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.