Specification
Wikipedia's Code 128 page explains the specification as follows:
A Code 128 barcode has seven sections:
- Quiet zone
- Start symbol
- Encoded data
- Check symbol (mandatory)
- Stop symbol
- Final bar (often considered part of the stop symbol)
- Quiet zone
The check symbol is calculated from a weighted sum (modulo 103) of all the symbols.
Data encoding
The font will handle the required zones and lines, in addition to the data we need to supply the start and stop symbols as well as a check symbol.
The section Check digit calculation explains that the checksum is calculated by summing the start code 'value' to the products of each symbol's 'value' multiplied by its position in the barcode string. The sum of the products is then reduced modulo 103. Since the start code value in this case is 103, of which modulo 103 is 0, it can be ignored and we only have to tally up the data symbols.
Using the Free barcode fonts @ dobsonsw which is a Code 128B, or Code set B, font which supports 95 characters, ASCII characters 32 through 127. To display the check symbol there are 9 additional overflow characters that are out of sequence which need to be accounted for.
As @egerardus worked out this particular font uses non standard start (353
) and stop (339
) symbols and a different range of overflow characters (8216, 8217, 8220, 8221, 8226, 8211, 8212, 0732, 8364
).
Implementation
The following is a working C# implementation of the barcode data encoding.
private string BarcodeEncode(string value)
{
int[] overChars = { 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8364 };
char[] valueChars = value.ToCharArray();
int[] checksumVals = new int[value.Length];
for (int n = 0; n < valueChars.Length; n++)
{
checksumVals[n] = (((byte)valueChars[n]) - 32) * (n + 1);
}
int checksum = checksumVals.Sum() % 103;
char check = (char)(checksum + 33);
if (checksum > 93)
check = (char)overChars[checksum - 94];
string start = ((char)353).ToString();
string stop = ((char)339).ToString();
return start + value + check.ToString() + stop;
}
Followed by the equivalent JavaScript implementation.
function barcodeEncode(value) {
var overChars = [8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8364];
var checksum = [...value]
.map((i, n) => (i.charCodeAt(0) - 32) * ++n)
.reduce((a, b) => a + b, 0) % 103;
return String.fromCharCode(353) + value
+ (checksum < 94
? String.fromCharCode(checksum + 33)
: String.fromCharCode(overChars[checksum - 94]))
+ String.fromCharCode(339);
}
nJoy!