Like the title says, I have a Code128 font that I would like to print barcodes with. However, the string needs to be encoded in Code128 to make the barcode font work. My app uses the Python3 language.
There used to be an example on the web somewhere how to encode the string for a Code128 font, but I can't find it anymore.
I do NOT want a string to .svg converter. I specifically want to convert a string to a Code128 encoded string.
Any references, code snippets in Python3 or documentation would be appreciated.
EDIT: I use the font from here.
This is an accepted answer, so I'm leaving the original code underneath. But I prefer this refinement.
def list_join(seq):
''' Join a sequence of lists into a single list, much like str.join
will join a sequence of strings into a single string.
'''
return [x for sub in seq for x in sub]
code128B_mapping = dict((chr(c), [98, c+64] if c < 32 else [c-32]) for c in range(128))
code128C_mapping = dict([(u'%02d' % i, [i]) for i in range(100)] + [(u'%d' % i, [100, 16+i]) for i in range(10)])
code128_chars = u''.join(chr(c) for c in [212] + list(range(33,126+1)) + list(range(200,211+1)))
def encode128(s):
''' Code 128 conversion for a font as described at
https://en.wikipedia.org/wiki/Code_128 and downloaded
from http://www.barcodelink.net/barcode-font.php
Only encodes ASCII characters, does not take advantage of
FNC4 for bytes with the upper bit set. Control characters
are not optimized and expand to 2 characters each.
Coded for https://stackoverflow.com/q/52710760/5987
'''
if s.isdigit() and len(s) >= 2:
# use Code 128C, pairs of digits
codes = [105] + list_join(code128C_mapping[s[i:i+2]] for i in range(0, len(s), 2))
else:
# use Code 128B and shift for Code 128A
codes = [104] + list_join(code128B_mapping[c] for c in s)
check_digit = (codes[0] + sum(i * x for i,x in enumerate(codes))) % 103
codes.append(check_digit)
codes.append(106) # stop code
return u''.join(code128_chars[x] for x in codes)
def encode128(s):
''' Code 128 conversion for a font as described at
https://en.wikipedia.org/wiki/Code_128 and downloaded
from http://www.barcodelink.net/barcode-font.php
Only encodes ASCII characters, does not take advantage of
FNC4 for bytes with the upper bit set.
It does not attempt to optimize the length of the string,
Code B is the default to prefer lower case over control characters.
Coded for https://stackoverflow.com/q/52710760/5987
'''
s = s.encode('ascii').decode('ascii')
if s.isdigit() and len(s) % 2 == 0:
# use Code 128C, pairs of digits
codes = [105]
for i in range(0, len(s), 2):
codes.append(int(s[i:i+2], 10))
else:
# use Code 128B and shift for Code 128A
mapping = dict((chr(c), [98, c + 64] if c < 32 else [c - 32]) for c in range(128))
codes = [104]
for c in s:
codes.extend(mapping[c])
check_digit = (codes[0] + sum(i * x for i,x in enumerate(codes))) % 103
codes.append(check_digit)
codes.append(106) # stop code
chars = (b'\xd4' + bytes(range(33,126+1)) + bytes(range(200,211+1))).decode('latin-1')
return ''.join(chars[x] for x in codes)