Python Code128 encoder for Code128 barcode font
Asked Answered
C

1

5

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.

Calque answered 8/10, 2018 at 22:10 Comment(2)
What font are you using? I don't think the mapping from codes to characters is standardized.Manville
@MarkRansom barcodelink.net/barcode-font.phpCalque
M
7

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://mcmap.net/q/2001884/-python-code128-encoder-for-code128-barcode-font/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://mcmap.net/q/2001884/-python-code128-encoder-for-code128-barcode-font/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)
Manville answered 9/10, 2018 at 4:34 Comment(2)
This is super useful. Fonts can apparently use different characters to encode the START and STOP characters. Hopefully there is documentation for the font you use.Pastorate
@TimRichardson as I said in the comments on the question, there's no standard for the mapping of codes to font characters. That means for a font to be usable, there must be documentation that defines the mapping. My only hope is that the code isn't too obscure to adjust the mapping as necessary.Manville

© 2022 - 2024 — McMap. All rights reserved.