Code 39 takes me way back to sinking my teeth into my first real barcode programming experience. Code 39 is a very simple and straightforward code set consisting of 43 unique representable characters and one start and stop character: the asterisk “*”. If you’ve never done any work with barcodes before, this is a no-brainer selection for an introductory symbology. As such, we can make this lesson a very simple one. I will explain how you can, using the code from the September 19th, 2013 post, generate real, scannable codes in minutes.
There are two setup arrays, and only one line of the four lines of JavaScript code is non-trivial. Here we go…
The Code 39 Setup
// Symbology-specific arrays var arrayCode39Bin = new Array ( '1010001110111010', '1110100010101110', '1011100010101110', '1110111000101010', // 0, 1, 2, 3 '1010001110101110', '1110100011101010', '1011100011101010', '1010001011101110', // 4, 5, 6, 7 '1110100010111010', '1011100010111010', '1110101000101110', '1011101000101110', // 8, 9, A, B '1110111010001010', '1010111000101110', '1110101110001010', '1011101110001010', // C, D, E, F '1010100011101110', '1110101000111010', '1011101000111010', '1010111000111010', // G, H, I, J '1110101010001110', '1011101010001110', '1110111010100010', '1010111010001110', // K, L, M, N '1110101110100010', '1011101110100010', '1010101110001110', '1110101011100010', // O, P, Q, R '1011101011100010', '1010111011100010', '1110001010101110', '1000111010101110', // S, T, U, V '1110001110101010', '1000101110101110', '1110001011101010', '1000111011101010', // W, X, Y, Z '1000101011101110', '1110001010111010', '1000111010111010', '1000100010001010', // -, ., (space), $ '1000100010100010', '1000101000100010', '1010001000100010', '1000101110111010'); // /, +, %, * var strCode39 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
Take these lines of code and add them to the bottom of the Setup portion of the file given out in the
Posted on
I don’t particularly care for line-by-line code reviews. I don’t think they convey much meaning, even to people who think like computers. But you have to understand the inner workings of the software published earlier before I turn you loose on society. Thankfully, there are only about ten lines of code in the software and three major areas, so covering them should be a breeze for both you and me. So, copy the source code from the last article into your favorite text editor and follow along. Trust me, this won’t hurt a bit. The three major sections are the setup data, the chunkifier and the rendering engine. The Setup The Chunkifier The Rendering Engine The Output There are no line feeds or carriage returns embedded in the output text for a very good reason covered earlier. The text consists only of HTML entities. So, it takes six HTML images to render that very simple pseudo-barcode we saw last time (near the anti-climactic “ta-da!”). Next time we are going to demonstrate doing something non-trivial with the rendering engine by hooking it up to some code that actually generates valid barcodes. Until next time, thanks for tuning in. In order to make this whole client-side barcode thing work, it is necessary to first develop the engine of rendering. I don’t know whether it was Hulk Hogan or Benjamin Parker who first coined the phrase: “With great power comes great responsibility.”. Regardless, there be great power here, and I’m counting on everyone to be good stewards and not use this power for evil. With the following couple dozen lines of code and configuration data, you too can make barcodes as realistic as the big boys. All you need to do is wrap the code in ‘<SCRIPT>’ tags as I am about to do and supply the necessary inputs. These are a fairly long string of ‘1’s and ‘0’s (that’s ones and zeroes, boys and girls, not lowercase ‘L’s and capital ‘o’s), a width and a height. As presented, this code is not particularly useful. The barcode symbol does not actually represent any readable value that I am aware of. The input is just a string of ‘1’s and ‘0’s used to illustrate the working software. Here’s what it looks like in a browser: In our next installment, we will walk through the rendering engine and see how it works. In the mean time, please feel free to copy the enclosed HTML / JavaScript into a local HTML file and go nuts with the three parameters. Until next time, thank you for tuning in. The first step to convert the “brute force” barcodes to JavaScript was to realize that 107 different bar line and space combinations were too many to be manageable. The idea was to enable JavaScript to draw the barcodes at run-time coming up with any combination of lines and spaces necessary to support any format. I did not want to use any recent inventions like Canvas or SVG because I want universal browser support. Every graphical web browser supports Portable Network Graphics (PNG) format. Most web browsers, since 1996, have supported JavaScript. While it is possible to disable scripting, when JavaScript capability is enabled, the software should work regardless of browser or platform. I did not want to put a bunch of fancy conditional “if Safari but not Opera” code in the software. After all, the goal of the code is to demonstrate for educational purposes how simply barcodes can be rendered. So, I stuck with my original brilliant idea and positioned a bunch of client-side PNG images next to one another. Because the original idea worked from thinking that barcodes are really depictions of disproportionately scaled Morse-code-like ‘1’s and ‘0’s, I needed an approach that would take any generic bit stream and render it. There are 256 unique bit values in a byte, but because 107 images were somewhat unwieldy in the “brute force” method, I decided to slim that down to something more manageable. I discarded 7-bits per image (128 combinations) and 6-bits per image (64 combinations) as options before I decided to try 5-bits per image. I suppose that I could have gone down to one bit per image, but I was concerned about performance. Perhaps I’ll save that experiment for later. A refresher is in order if you are unfamiliar with the exact technique I used to get the bitmapped graphic into base-64 PNG images. I’m not going to get too deep into the details of Barcode Tools and Techniques in this or future postings, so a detailed discussion can be found Under Barcodes->HTML->Code 128 Barcode on this website. I used the same technique that I used for the Code 128 “brute force” method for each possible bitmap representing 0-31, or ‘00000’ to ‘11111’ in binary. Unfortunately, the graphical depictions, once converted to PNG, then base-64 were being optimized in a number of cases, but not all. Therefore, I ended up with an unruly mess of base-64 text that I wanted to break down to save some bytes. I decided to try doubling the size of the bitmap so that each bit was represented by a 2×2 pixel map of all black or all white. This yielded much better results as depicted here. In the next installment, we will walk through the JavaScript code that renders the bars. It’s really straight-forward and easy to follow. Until next time, thank you for tuning in. When we last left the barcode software we had a set of images that represented every character in the Code 128 symbology. There was a Microsoft ExcelWebApp (really a downloadable spreadsheet) that you could use to type in a string to generate your own barcodes. There was also a very in-depth discussion about how you can roll your own barcodes using this same technique. If you have a little HTML experience, this set of images is all that you need to put a barcode on a website or embed one into an e-mail. The drawback of this method is that it is a little cumbersome and not very highly interactive. If you want several dozen barcodes, the “brute force” technique, as I call it, is not very efficient. That is why, during my original postings, I hinted that the real ‘Wow!’ factor is in utilizing JavaScript to take a lot of the drugework out. This technique is what I am ready to share now. The barcodes have been streamlined and now provide the ability to represent any one of dozens of different symbologies including Code 128, Code 39, Interleaved 2 of 5, UPC and even 2D symbologies like QR Code and PDF417. The 2D symbologies had me stumped for a little while because of a much more elaborate error-correction scheme utilizing Reed-Solomon codes. I will have more on that later, but suffice it to say 2D barcodes rely on a buffer of error-correction bytes. These bytes not only inform the scanner if a barcode has been damaged, but help the barcode reader piece together the correct data in the barcode so it doesn’t necessarily have to report an unreadable symbol. In order to produce the JavaScript driven version of the barcodes, I had to make a couple of changes: In order to most efficiently use JavaScript to produce barcodes, the specific barcode symbology (Code 128, UPC, Datamatrix, etc.) needs to be “built” at run-time. Otherwise you find yourself spending weeks in drawing packages rendering little bit-wise versions of each character set. What you can do with JavaScript, instead, is give the software the means of producing bars and spaces with a limited set of PNG files and drive the data that is specific to the methodology out to the barcode generator. In other words, once JavaScript knows how to produce the bars and lines and spacing, you can feed it flags or ‘1’s and ‘0’s to explain the symbol specific messages. As I mentioned in an earlier post, barcodes are a computer’s Morse code. As such, the JavaScript barcode rendering engine is like the telegraph machine and wiring. The operator software is separate and it alone knows the details of each symbology. The big disadvantage of the new method is the fact that we will not be seeing the alternate and title text associated with each barcode character. Since the Javascript that generates the bars is no longer speaking any particular barcode dialect, it doesn’t really know what it is rendering. Separating the “operator” from the “equipment” allows the operator to specialize in the idiosyncrasies of the symbology. All symbology-specific code can be held in an external JavaScript file, so it only loads if the application requires it. That means another visit to the server, but a much smaller initial package and simpler symbologies like Interleaved 2of5 and Code 39 do not have to bear the overhead of QR Code or PDF417. Separation also allows the “equipment” to be super lean and lightning fast. Rendering a barcode becomes its “hedgehog” and that JavaScript function can forget about every other thing. Before I divulge the complete package, I want to walk through the creation of the new software. I also want to have an understanding, up front, that this software has been contrived by yours truly. Therefore, in its published form, it will contain the following text: You are approved to use the software as you see fit, but if you use the software in its entirety in a republished work, it is expected that credit will be given and the copyright notice will not be removed. In the next installment of this series, we will dive into the mechanics of the barcode generation code. Until next time, thank you for tuning in.Code Review or Root Canal? Hmmm…
The setup data consists of the necessary string literals to enable the rendering engine to draw the images using base-64 converted PNG files. This front matter takes up almost 1800 bytes and consists of the declaration for the JavaScript arrays array5bit_A, array5bit_B, stringStart, stringMid and stringEnd. Once these arrays are defined any barcode symbology can use them. So they are pretty important and well worth the space they take up.
Sounds like a subtitle for a good slasher movie, eh? The chunkifier is the four lines of code starting with the initialization of the intRawmod variable and ending with the for loop that populates the arraySeq array. In short, what the chunkifier does is break down a long string of ones and zeroes into a sequence of 5-bit integers.
The rendering engine takes the sequence of 5-bit integers created by the chunkifier and builds the <img> elements necessary to render the array. This is a very simple loop and uses the integers found in the sequence to look up the unique text found in array5bit_A and array5bit_B and patch it together with the start, middle and end string constants so we have an <img> element that parses and scales to display a series of bars and spaces.
What you would see, if you used the rendering engine to output to a text file from the demonstration at the end of the last article is:<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAA/wAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAASTUCAqHeHtMAAAAASUVORK5CYII=" width="10" height="40"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAKFYBA46vJCAAAAAASUVORK5CYII=" width="10" height="40"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAAAAAAAAAAAAAAAAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAUUYCA7QBErsAAAAASUVORK5CYII=" width="10" height="40"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAA/wAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAASTUCAqHeHtMAAAAASUVORK5CYII=" width="10" height="40"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAA/wAAAAAAAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAASU4CA+16cNAAAAAASUVORK5CYII=" width="10" height="40"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAABAAAAAAAAAP8AAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAbjUDAlvFFR8AAAAASUVORK5CYII=" width="10" height="40">
… Comes Great Responsibility.
<!DOCTYPE HTML>
<html>
<head>
<title>Notionovus Barcode Prototype</title>
<script type="text/javascript">
// The MIT License (MIT)
// Copyright (c) 2013, Notionovus, LLC.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// Generic arrays for drawing 5-bit graphics. Building blocks for all barcode symbologies
// Painstakingly derived gobblety-goop, but essentially the two middle sections of image data unique to each graphic
var array5bit_A = new Array ( 'f//AAAAAAAAAAAAAAAAAAAA', 'f//AAAAAAAAAAAAAAAAAAAB', 'f//AAAAAAAAAAAAAAEAAAD/',
'f//AAAAAAAAAAAAAAEAAAAA', 'f//AAAAAAAAAQAAAP8AAAAA', 'f//AAAAAAAAAQAAAP8AAAAB', 'f//AAAAAAAAAQAAAAAAAAD/',
'f//AAAAAAAAAQAAAAAAAAAA', 'f//AAABAAAA/wAAAAAAAAAA', 'f//AAABAAAA/wAAAAAAAAAB', 'f//AAABAAAA/wAAAAEAAAD/',
'f//AAABAAAA/wAAAAEAAAAA', 'f//AAABAAAAAAAAAP8AAAAA', 'f//AAABAAAAAAAAAP8AAAAB', 'f//AAABAAAAAAAAAAAAAAD/',
'f//AAABAAAAAAAAAAAAAAAA', 'QD/AAD/AAAAAAAAAAAAAAAA', 'QD/AAD/AAAAAAAAAAAAAAAB', 'QD/AAD/AAAAAAAAAAEAAAD/',
'QD/AAD/AAAAAAAAAAEAAAAA', 'QD/AAD/AAAAAQAAAP8AAAAA', 'QD/AAD/AAAAAQAAAP8AAAAB', 'QD/AAD/AAAAAQAAAAAAAAD/',
'QD/AAD/AAAAAQAAAAAAAAAA', 'QD/AAAAAAAA/wAAAAAAAAAA', 'QD/AAAAAAAA/wAAAAAAAAAB', 'SL/AADeAAAA/gAAAAIAAAD+',
'QD/AAAAAAAA/wAAAAEAAAAA', 'QD/AAAAAAAAAAAAAP8AAAAA', 'QD/AAAAAAAAAAAAAP8AAAAB', 'QD/AAAAAAAAAAAAAAAAAAD/',
'QD/AAAAAAAAAAAAAAAAAAAA');
var array5bit_B = new Array ( 'US0CAuSD38g', 'UUYCA7QBErs', 'ajEDAm49ReY', 'UUoCA+juogg', 'bjEDAjQrOn0', 'bkoDA3iPVH4',
'ajUDAt82atY', 'UU4CA1nljTg', 'cjEDAghkmFU', 'ckoDA0TA9lY', 'izUEAhrxcbg', 'ck4DAxY8F10', 'bjUDAlvFFR8', 'bk4DAxdhexw',
'ajkDAr7LFAw', 'UVICAyQ+UJI', 'TTECAq7UnEM', 'TUoCA+Jw8kA', 'ZjUDAmZGozo', 'TU4CA7CME0s', 'ajUDAvnk9E4', 'ak4DA7VAmk0',
'ZjkDAtle3bI', 'TVICAxOyzrM', 'STUCAqHeHtM', 'SU4CA+16cNA', 'h6QEAZKdo54', 'SVICA62zYxM', 'RTkCAqx1lb4', 'RVICA/z3WM0',
'QT0CAkdoxRU', 'KFYBA46vJCA');
// Painstakingly derived gobblety-goop, but essentially the front, back and mid-matter common to all barcode images...
var stringStart = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/A';
var stringMid = 'AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA';
var stringEnd = 'AAAAASUVORK5CYII=" width="';
//
// Insert Symbology-specific arrays here
//
function genBarcode(inputString,intWidth,intHeight) { // Input is a long string of 1's and 0's, output is the HTML <img> stack
// Pads to the last character to ensure length is divisible by 5
var intRawmod = inputString.length % 5; // Modulo 5 remainder
if (intRawmod > 0) for (var i = 0; i < 5 - intRawmod; i++) inputString += "0"; // If not evenly divisible, pad with zeroes
var arraySeq = new Array (intChunks = inputString.length / 5); // Create array for as many chunks as are now in input string
for (var i = 0; i < intChunks; i++) arraySeq[i] = parseInt(inputString.substr(i * 5, 5), 2); // Converts string of 1's and 0's to integer array
// Takes integer array and converts to "<img ...>" graphics for display
var resultString = "";
for (var i = 0; i < arraySeq.length; i++) {
resultString += stringStart + array5bit_A[arraySeq[i]] + stringMid + array5bit_B[arraySeq[i]] + stringEnd + intWidth + '" height="' + intHeight + '">';
}
return resultString;
}
</script>
</head>
<body>
<script>
document.write(genBarcode('1100011111000011100011001011',10,40));
document.write(' ta-da! ');
</script>
</body>
</html>
Mods Required
The base-64 table that was generated had a good symmetry to it, and I took this as a good sign and moved on. Each image had 65 identical bytes of front matter, a patch of 23 bytes unique to each number, another 32 identical bytes, 11 unique representations again, and the last 17 bytes were identical. Since I wanted to create the HTML to represent each unique image in one line of JavaScript, this seemed to suit my purpose.
There were some considerations. Since I was rendering barcodes 5-bits at a time, I had to chunkify a string of ‘1’s and ‘0’s of undetermined length into 5 bits. Since not all barcode bit streams are divisible by 5, I had to pad the last remaining bits with ‘0’s to get all the rendering to come out even. Since the ‘0’s just add a maximum of 4 bits of white space to the right hand side of the barcode, and since a minimum quiet zone must be maintained anyway, this has not been an issue. The software generally adds ‘0’s to the front and back of every bit stream regardless.Barcodes Revisited
The Symbol Agnostic “Metafont”
Separated For Their Own Good
Conceptual Introduction
The MIT License (MIT)
Copyright (c) 2013, Notionovus, LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.