Anatomy of a Barcode - barcode

I've been searching around for how to understand how to generate a bar code and haven't found any useful information.
Basically, a bar code has these features:
Black bars of different widths.
White bars of different widths.
I would like to know what the specification is for the widths of the bars. That's it. I can find information regarding the data to put into a bar code. I just haven't found any information on how you translate some arbitrary data into the different black and white bars of different widths. I would like to know how many different widths there are as well (for each black and white bars).

The USPS supports both Code 128B and Code 39 barcodes. For international mail it is recommended that you use Code 39. The different symbologies (of which, Code 128 and Code 39 are but two examples) use very different encoding methods and so the answer for how a number "8" is made, for example, is dependent on the symbology selected.
In order to know what the widths of bars and spaces there are for each character, you need to know what symbology you are talking about first. After that point, Wikipedia is your friend. A good tip here is not to think of them in terms of widths, but as ratios.
The dark and light areas of a barcode are proportional to one another because it is impossible to know how far away the scanner will be from the printed code. So you don't want software that measures black bar widths or white spaces in terms of millimeters or even pixels. Instead you want to imagine the ability to print the tiniest barcode as dots and then use your printing mechanism to scale.
For example: the Code 39 representation of the number "8" is a thick bar followed by a thin space followed by a thin bar followed by a thick space followed by a thin bar followed by a thin space followed by a thick bar followed by a thin space followed by a thin bar followed by a thin space. That's almost as painful to read as it was to write.
So to avoid all that, I just think of the ratio between thin and thick for Code 39 to be 1:3 and use ones to represent bars (black dots) and zeroes to represent white spaces. In that context, a Code 39 number "8" looks like "1110100010111010". There is no sense trying to figure out widths in microns or millimeters or angstroms. You can put a barcode on a tardigrade or a corn field if you have the right equipment. The widths will change, but the ratios will not.
To illustrate I have used our Code 39 number "8" as an example:
<table><tr><td><span><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAAAAAAAP8AAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAARVICA/z3WM0AAAAASUVORK5CYII=" width="30" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAAAAAAAAAAAAAEAAAD/AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAajEDAm49ReYAAAAASUVORK5CYII=" width="30" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAAAAAAAP8AAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAARVICA/z3WM0AAAAASUVORK5CYII=" width="30" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAUS0CAuSD38gAAAAASUVORK5CYII=" width="30" height="70"></span></td><td width=150px>
The barcode on the left is five times wider than the one on the right. (same code)</td><td>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAAAAAAAP8AAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAARVICA/z3WM0AAAAASUVORK5CYII=" width="6" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAAAAAAAAAAAAAEAAAD/AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAajEDAm49ReYAAAAASUVORK5CYII=" width="6" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/AQD/AAAAAAAAAAAAAP8AAAABAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAARVICA/z3WM0AAAAASUVORK5CYII=" width="6" height="70"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAQAAADLaIVbAAAANUlEQVQIHQEqANX/Af//AAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAUS0CAuSD38gAAAAASUVORK5CYII=" width="6" height="70"></td></tr></table>

Related

DirectWrite renders issues and metric scaling inaccuracy

I have DirectWrite setup to render single glyphs and then shape them programmatically based on the glyph run and font metrics. (Due to my use case, I can't store every full texture in an OpenGL texture otherwise it's essentially a memory leak. So we store each glyph into one texture to lay them out glyph by glyph.)
However, I have two issues:
Inconsistent rendering results.
Scaling metrics leads to inconsistent distances between glyphs.
These results are are transferred to a bitmap using Direct2D and WIC bitmap (CreateWicBitmapRenderTarget).
Let's look at an example, font size 12 with Segoe UI.
Full string rendered 1st line is rendered using DrawTextLayout drawn with D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT. 2nd line is drawn with each Glyph using DrawGlyphRun with DWRITE_MEASURING_MODE_NATURAL. 3rd is rendered with paint.net just for reference.
This leads to the second issue, the distance between each letter can be off. I am not sure if this is a symptom of the previous issue. You can see the distance between s and P is now 2 pixels when drawn separately. Because i is no longer 3 pixels wide, it visually looks too close to c now when zoomed out. p and e look too close.
I have checked the metrics, and I am receiving the right metrics from the font from shaping. Above string metrics from DirectWrite : [1088.0, 1204.0, 1071.0, 946.0, 496.0, 1071.0, 869.0]. I am comparing output with Harfbuzz: [S=0+1088|p=1+1204|e=2+1071|c=3+946|i=4+496|e=5+1071|s=6+869] which is correct.
To convert to DIP I am using this formula for the ratio multiplier: (size * dpi) / 72 / metrics.designUnitsPerEm
So with a default DPI of 96 and default size of 12 we get the following ratio: 0.0078125.
Let's look at S is 1088. So the advance should be 1088 * 0.0078125 = 8.5. Since we can't write between half a pixel, which way do we go? I tried every value from the lsb, to the advance, to render offset in every combination of flooring, ceiling, rounding, converting to int. Whichever way I choose, even if it fixes it for one situation, I'll test with another font, or another size, it will be one or two pixels too close in another string. I just can't seem to find a proper balance that is universal.
I am not really sure where to go from here. Any suggestions are appreciated. Here is the code: https://github.com/pyglet/pyglet/blob/master/pyglet/font/directwrite.py#L1736
EDIT: After a suggestion of using DrawGlyphRun using the full run, it does appear exactly what the DrawTextLayout outputs. So the DrawGlyphRun should produce the same appearance. Here's where it gets interesting:
Line1: DrawTextLayout
Line2: Single glyphs drawn by DrawGlyphRun
Line3: All glyphs drawn using DrawGlyphRun
You can see something interesting. If I render each 'c' by itself (right side), you can see that it has 4 pixels on the left of the character by itself. But in the strings it looks like it's missing. Actually, taking a deeper look, and a color dropper, it appears the color is indeed there, but it's much darker. So somehow each glyph is affecting the blend of the pixels around it. I am not really sure how it's doing this.
EDIT2: Talking with another, I think we narrowed this down to anti-aliasing. Applying the antialias to the whole string vs each character produces a different result. Setting D2D1_TEXT_ANTIALIAS_MODE_ALIASED each character looks and appears exactly the same now compared to both.

MacOS CALayer Character Spacing

I have a problem which I hope you can help me solving.
I'm creating a program using Xamarin.Mac (C# for Mac) and I need to draw a DNA sequence (ATGC and so on). However, I need to know the exact position of each character so I can draw several other objects which should be aligned with the characters in DNA sequence.
Screenshot of the Windows version of my app which illustrates the behavior I'm looking for:
Currently I'm looking to use the CALayer drawing method, which appears to be fast enough to render 12 lines of 70 characters in less than 50 ms. CALayers are not fast enough to render 1000 CATextLayers with one (A/T/G/C) character each, so (I think) I need to render them as lines with specific spacing. This means that I need to have exactly 10 (example) pixels between the center of each character.
However, I cannot find a way to do this.
The NSAttributedString Kerning seems be added to an unknown existing tracking (or spacing) of the font, and thus may be used with monospace fonts but still results in an unknown actual spacing.
I CAN get around the issue by trial and error until the letter spacing appears to match the desired spacing, but I'm not very confident in robustness of this method across different devices (screen resolutions). This requires that I use a monospace font, which is okay, but not optimal.
Is it possible to have specific character spacing using a single CATextLayer and what are my options if not? is it possible to have 1000 characters drawn individually without a huge performance impact?
Thank you.

How to calculate the width (in dots) of this zpl barcode?

^XA
^FO0,90^AD^BY3
^BCN,100,Y,N,Y,A
^MD10
^FD1458622235534^FS
^XZ
Using Label Viewer I was able to play around with ZPL and after reading some documentation figured out that ^FO0,90 is what positions the barcode. 0 is for the number of dots from the left and 90 is for the number of dots from the top.
My question is, how can the width of the above bar code be calcuated in dots? If I know the width of the barcode, I can then center it programmatically.
The printer's resolution is 203dpi and given a 3' (width) x 2' (length) tag, that is 610 dots across.
What is the formula to calculate the width of a ZPL Barcode?
The Code 128 barcode includes three modes. The "A" in your ^BC means that the barcode algorithm will automatically select the best mode based on the placement of where the letters are mixed in with the numbers, and/or how many numbers are in a row. This results in barcodes that vary in length depending on their content.
You can change that A to an N. This will make the width easy to estimate, even if it's not the most space efficient.
For the N option: count 106 dots, total, for the bookends, and 33 dots for each digit.
For the N + Subset C option: If you can say for sure that you will always have an even number of digits (no letters, spaces, or other symbols). You can force the barcode into subset C mode. Count 104 dots for the bookends, and 33 dots for every two digits. But you must have an even number of digits.
^BCN,100,Y,N,Y,N
^FD>;1422335544^FS
The >; tells ZPL to render this as subset C.
If you know that you will need to support alphanumeric barcodes, then stick with the A. This is where things get harder.
You will need to model the barcode algorithm in your programming language of choice. Perhaps you could find an existing library, as Code 128 is a very popular barcode. Use the library to render the barcode in memory. You may have to play with the parameters to get it to produce a barcode equal to your ZPL output. Then have your program use the output of the library to determine the width of the barcode.
If your barcode is always going to be 13 digits, then automatic centering is a moot point. The barcode will always be the same width, even in automatic mode. Find the ^FO that looks like it's centered on the label, and stick with that. This barcode is 368 dots wide. Try ^FO121,90.
I didn't calculate the width of the barcode, I measured it by rendering the label to a Gif and then examining the label in a paint program that would let me count the dots.
I suggest you have a look at the Code 128 wikipedia article for the details.
The natural unit of length for code 128 is the narrow bar width noted x (in your ZPL code set to 3 dots). A code 128 barcode (excluding the two 10x quiet zones) is made up of
a start character (11x wide)
n encoded character of width 11x
a CRC (11x wide)
a stop character (12x wide)
If your data takes n encoded characters, the length of the barcode is (34 + n*11)x. In your case, x is 3 dots, so at 8dot/mm the barcode will be (12.75 + n*4.125)mm wide.
You have to look into the encoding to figure out n. Minimal encodings are not unique, but in your case the data will be encoded with 8 barcode characters: 6 code C character (for 6 pairs of digits), 1 switch code character and 1 code A character (for the last digit). The barcode should be 45.75mm / 366dot wide.
There is a little issue with your ZPL. You specified a UCC checkcode on a non UCC barcode. I am not familiar with UCC/GS1-128 barcodes but that might introduce extra barcode characters or be irrelevant.
Also you might consider padding your timestamp with a leading 0. With Code 128, pairs of digit have a better encoding. A 14-digit barcode will be be 4.125mm shorter.
I just mentionned the quiet zone, barcode readers require them.

"Barcode" reading from scanned image

I want to read a barcode from a scanned image that I printed. The image format is not relevant. I found that the scanned images are of very low quality and can understand why it normal barcodes fail.
My idea is to create a non standard and very simple barcode at the top of each page printed. It will be 20 squares in a row forming a simple binary code.Filled = 1, open = 0. It will be large enough on aA4 to make detection easy.
At this stage I need to load the image and find the barcode somewhere at the top. It will not be exactly at the same spot as it is scanned in. Step into each block and build the ID.
Any knowledge or links to info would be awesome.
If you can preset a region of interest that contains the code and nothing else, then detection is pretty easy. Scan a few rays across this region and find the white/black and black/white transitions. Then, knowing where the "cells" should be, you known their polarity.
For this to work, you need to frame your cells with two black ones on both ends to make sure to know where it starts/stops (if the scale is fixed, you can do with just a start cell, but I would not recommend this).
You could have a look at https://github.com/zxing/zxing. I would suggest to use a 1D bar code, but wide enough to match the low resolution of the scanner.
You could also invent your own bar code encoding and try to parse it your self. Use thick bars for 1 and thin lines for 0. A thick bar would be for instance 2 white pixels, 4 black pixels. A thin line would be 2 white pixels, 2 black pixels and 2 white pixels. The last two pixels encode the bit value.
The pixel should be the size of the scanned image pixel.
You then process the image scan line by scan line, trying to locate the bar code.
We locate the bar code by comparing a given pixel value sequence with a pattern. This is performed by computing a score function. The sum of squared difference is a good pick. When computing the score we ignore the two pixels encoding the bit value.
When the score is below a threshold, we found a matching pattern. It is good to add parity bits to the encoded value so that it's validity can be checked.
Computing a sum of square on a sliding window can be optimized.

Does scaling of barcode image damages it?

I have a barcode image. I have to make it smaller.
Can that damage the barcode?
Proportional scaling
Not proportional scaling (only height changes)
Barcodes are: Type UPC-A / EAN-13 "vertical lines". Sorry not an expert in barcodes, thought the type of barcode would not be important. Scaling is moderate, the image does not lose relevant data.
Regular barcode (=vertical stripes) is recognized by the relative width of the lines. Thus, the horizontal height only matters for robustness against diagonal scanning. If the codes are scanned with a hand scanner, I'd just scale the height (or crop the image). In any case, the different widths of the lines should still be clearly visible. There may be compliance rules suggesting minimum proportions for a given barcode standard.
For regular linear product barcodes, the simple answer is yes, you can scale it (both case are safe).
However, if you scale too far and the bars end up too close together, you will start to get a high level of read errors.
You'll need to test it with an appropriate barcode reader to make sure you haven't scaled too much.
When scaling a barcode, there are several things you must keep in mind.
1) You get the absolute sharpest edges in a barcode if each module (the narrowest bar) is a whole number of pixels wide.
2) If the module width is not a whole number of pixels, produce a barcode where the width of each module is the truncated whole number and use bilinear interpolation to scale up. This will give you at most one pixel of gradient at the edges.
3) Be careful when buying a barcode library, choose one that includes built-in scaling that preserves the barcode, such as this one or this one. Barcodes have special demands that image processing normally does not have, such as pixel-perfection. Using e.g. Gimp might damage the barcode.

Resources