2

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/

michael
  • 686
  • 2
  • 11
  • 21

1 Answers1

1

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>
Mark
  • 106,305
  • 20
  • 172
  • 230
  • I figured reversing the key/value in the array would be the way to do it since it's not generating the code anymore. I'm still learning D3, thanks for your help! – michael Jan 27 '16 at 18:12
  • Also I found that you switched out a zero for a period in binary value. – michael Feb 17 '16 at 22:41
  • @michael, zero for period? Please elaborate. – Mark Feb 17 '16 at 22:59
  • basically you just accidentally switched the binary values for `"." = "110010101101"` with a `"0" = "101001101101"` — I found this when scanning with the barcode scanner. No worries. – michael Feb 17 '16 at 23:09
  • Here's my JSFiddle with the correct encoding. https://jsfiddle.net/michaelreynolds/661rzty8/ – michael Feb 17 '16 at 23:19