代码之家  ›  专栏  ›  技术社区  ›  theGtknerd

用于Code128条形码字体的Python Code128编码器

  •  0
  • theGtknerd  · 技术社区  · 6 年前

    正如标题所说,我有一个Code128字体,我想打印条形码。但是,字符串需要用Code128编码才能使条形码字体正常工作。我的应用程序使用Python3语言。

    在网上曾经有一个例子,如何将字符串编码为Code128字体,但我再也找不到了。

    我愿意 不是

    任何引用,代码片段在Python3或文档将不胜感激。

    编辑:我使用的字体来自 here .

    1 回复  |  直到 6 年前
        1
  •  5
  •   Mark Ransom    6 年前

    这是一个公认的答案,所以我把原来的代码留在下面。但我更喜欢这种精致。

    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)
    
    推荐文章