Search code examples
javascriptd3.jsbinarybarcodecode39

Barcode Code 39 javascript encoding


I'm trying to encode a code 39 Barcode by modifying some D3 javascript.

The problem is I don't understand how code 39 barcodes are encoded. It looks like they use 12 bit binary to encode the characters.

How can I decode a string of characters like '598649' into it's 12bit binary equivalent, preferably using D3.js?

characters = {
'100100100101': '$',
'100100101001': '/',
'100101001001': '+',
'100101011011': '-',
'100101101011': 'X',
'100101101101': '*',
'100110101011': 'V',
'100110101101': ' ',
'100110110101': 'Z',
'101001001001': '%',
'101001011011': '7',
'101001101011': '4',
'101001101101': '0',
'101010011011': 'G',
'101010110011': 'Q',
'101011001011': 'D',
'101011001101': 'J',
'101011010011': 'N',
'101011011001': 'T',
'101100101011': '2',
'101100101101': '9',
'101100110101': '6',
'101101001011': 'B',
'101101001101': 'I',
'101101010011': 'L',
'101101011001': 'S',
'101101100101': 'F',
'101101101001': 'P',
'110010101011': 'U',
'110010101101': '0',
'110010110101': 'Y',
'110011010101': 'W',
'110100101011': '1',
'110100101101': '8',
'110100110101': '5',
'110101001011': 'A',
'110101001101': 'H',
'110101010011': 'K',
'110101011001': 'R',
'110101100101': 'E',
'110101101001': 'O',
'110110010101': '3',
'110110100101': 'C',
'110110101001': 'M',
}

Here is some code I've been working with so far. The previous code was generating random binary then matching the key to value. I'd like to do the opposite, so I'm not sure if I should just create a second array with key/values reversed.

    //var num= prompt("Enter num")
    //console.log(parseInt(num, 10).toString(2))

    //var decnum=892938
    //alert(decnum.toString(2))

    // var b = parseInt( a, 2 )




    // var str = '34566'
    // var found = str.match(/[01]{12}/g).map(['110100101101','101100101101', '101100101011', '101100101101', '110110010101', '110100101101'])

    //str.match(/[01]{12}/g).map(characters)
    //console.log(characters[v])
    //console.log(found)


    var str = ['110100101101','101100101101', '101100101011', '101100101101', '110110010101', '110100101101']
    //var barcode_array = str.match(/[01]{12}/g).map(Object.keys(characters))

    //console.log(barcode_array)

    //split into array
    var barcode_input = ['110100101101','101100101101', '101100101011', '101100101101', '110110010101', '110100101101']

    //map to binary characters
    //console.log(barcode_input.range(Object.keys(characters)))

Here's the Fiddle https://jsfiddle.net/6szmwkgm/6/

code is modified from Christopher Manning http://bl.ocks.org/christophermanning/4324236 For reference here's another code 39 script http://notionovus.com/blog/code-39-barcode-biscuits/


Solution

  • The encoding you are building can be done by using the characters object as a simple lookup table. Take each character and lookup it's line pattern, build an array of these and then process them.

    The code you are working off of is a doing a lot more work then you seem to need. I used it a starting point and then cut it down into the bare minimum.

    Note, I didn't have a scanner handy to test this, so let me know if it gives you any trouble.

    Here's a commented code snippet:

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
      <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    
      <style type="text/css">
        body {
          display: block;
          margin: 0;
          background-color: #FFF;
        }
        
        text {
          font-family: monospace;
          font-size: 1.5em;
          text-anchor: middle;
        }
        
        path {
          fill-opacity: 0;
        }
      </style>
    </head>
    
    <body>
      <script type="text/javascript">
    
    		var svg = d3.select("body")
    		  .append("svg")
    		  .attr("width", 300)
    		  .attr("height", 300);
    
            // input barcode
    		var barcode = "598649";
    
            // some configuration items
    		var config = {
    		  "height": 100,
    		  "x": 10,
    		  "margin": 20
    		};
        
            // map each character to it's pattern
            // note I reversed it from the sample
            // to make lookups on each letter easier
    		var characters = {
    		  "0": "110010101101",
    		  " ": "100110101101",
    		  "1": "110100101011",
    		  "2": "101100101011",
    		  "3": "110110010101",
    		  "4": "101001101011",
    		  "5": "110100110101",
    		  "6": "101100110101",
    		  "7": "101001011011",
    		  "8": "110100101101",
    		  "9": "101100101101",
    		  "$": "100100100101",
    		  "%": "101001001001",
    		  "*": "100101101101",
    		  "+": "100101001001",
    		  "-": "100101011011",
    		  "/": "100100101001",
    		  "A": "110101001011",
    		  "B": "101101001011",
    		  "C": "110110100101",
    		  "D": "101011001011",
    		  "E": "110101100101",
    		  "F": "101101100101",
    		  "G": "101010011011",
    		  "H": "110101001101",
    		  "I": "101101001101",
    		  "J": "101011001101",
    		  "K": "110101010011",
    		  "L": "101101010011",
    		  "M": "110110101001",
    		  "N": "101011010011",
    		  "O": "110101101001",
    		  "P": "101101101001",
    		  "Q": "101010110011",
    		  "R": "110101011001",
    		  "S": "101101011001",
    		  "T": "101011011001",
    		  "U": "110010101011",
    		  "V": "100110101011",
    		  "W": "110011010101",
    		  "X": "100101101011",
    		  "Y": "110010110101",
    		  "Z": "100110110101"
    		};
    
            // build you data array
    		var data = [];
    		// Code 39 barcodes start with a *
    		data.push('100101101101');
    		barcode.split("").forEach(function(d, i) {
              // for each character, append the patter to our array
    		  data.push(characters[d]); //<-- look up for each character
    		});
    		// Code 39 barcodes end with a *
    		data.push('100101101101');
    		
            // set up line function
    		var line = d3.svg.line()
    		  .x(function(d) {
    			return d.cx = d.x
    		  })
    		  .y(function(d) {
    			return d.cy = d.y
    		  })
    		  
            // group all the barcode paths
    		var g = svg.append('g')
    		  .attr('class', 'barcode');
    
            // set up the data attributes necessary
    		var path = g.selectAll('path')
    		  .data(data.map(function(c) {
    			  return c + '0' // put a space between each character
    			}).join('').split('')
    			.map(function(d, i) {
    			  return [{
    				c: d,
    				x: config['margin']+ (i * 1.2),
    				y: config['margin']
    			  }, {
    				c: d,
    				x: config['margin'] + (i * 1.2),
    				y: config['margin'] + config['height']
    			  }]
    			})
    		  );
    
            
    		path.enter()
    		  .append('path');
    
            // draw the barcode
    		path
    		  .style("stroke", function(d) {
    			return d[0].c == '1' ? '#000' : '#FFF'
    		  })
    		  .style("stroke-width", 1.2)
    		  .attr("d", line);
    
    		path.exit().remove();
    		
            // add the text underneath
    		var text = svg.selectAll('text')
    		  .data([barcode])
    		
    		text.exit().remove();
    		
    		text.enter()
    		  .append('text');
    		
    		text
    		  .text(barcode)
    		  .style('fill', 'black')
    		  .attr('y', config.margin + config.height + 15)
          .attr('x', g.node().getBBox().width/2 + config.margin);
    
      </script>
    </body>
    
    </html>