Штрих-код печати отображается в окне графика иначе, чем в сохраненном файле .pdf - PullRequest
0 голосов
/ 24 октября 2018

У меня возникли проблемы с сохранением моего PDF должным образом.Я пытаюсь нанести этикетку со штрих-кодом и затем сохранить ее в формате PDF, как показано в следующем коде.Я установил шрифт code128.ttf на мои окна.Кроме того, я попытался установить аргумент .savefig dpi в fig.dpi, как описано в этом сообщении.

import os

import matplotlib.pyplot as plt

from matplotlib import font_manager as fm


def draw_label(label, label_dimensions_x=3.8189, label_dimensions_y=1.41732):

    # import barcode code128 font
    fpath = os.path.join("path", "to", "font", "code128.ttf")

    prop = fm.FontProperties(fname=fpath, size=58)

    fig, ax = plt.subplots(1, figsize=(label_dimensions_x,
                                       label_dimensions_y))

    plt.axis('off')
    plt.xticks([], [])
    plt.yticks([], [])
    plt.tight_layout()
    plt.xlim(0, label_dimensions_x)
    plt.ylim(0, label_dimensions_y)

    # plot barcode
    plt.text(label_dimensions_x / 2, label_dimensions_y / 2, label,
             ha='center', va='bottom',
             fontproperties=prop)

    plt.show()

    try:
        plt.savefig(os.path.join("path", "to", "output", label + '.pdf'),
                    dpi=plt.gcf().dpi)
    except PermissionError:
        logging.warning("Close the current label pdf's before running this script.")

    plt.close()

    return

draw_label('123456789')

Это - это то, что выводится вокно графика.

Это - это то, что выводится в сохраненном файле .pdf, и это происходит для всех видов этикеток - это не так, как если бы числа от 1 до 9, кроме 8, не были напечатаны,РЕДАКТИРОВАТЬ: Если я заменяю обычный шрифт текста (в данном случае Frutiger Roman) на code128.ttf и устанавливаю plt.axis ('on'), текст не обрезается, см. this .Признаюсь, это не красиво и не очень хорошо, но все же должно быть читаемым.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Вы слишком усложняете вещи, используя matplotlib и шрифт.Непосредственное создание изображения и его сохранение в файле PDF не намного сложнее и гораздо надежнее.

Как отмечает Брайан Андерсон , недостаточно кодировать символы в вашей строке,Вам нужно добавить стартовый код, контрольную сумму и код остановки, чтобы сделать полный штрих-код.Функция code128_codes ниже делает это, оставляя преобразование в изображение в качестве отдельного шага.

from PIL import Image

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)])

def code128_codes(s):
    ''' Code 128 conversion to a list of raw integer codes.
        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 codes

_code128_patterns = '''
    11011001100 11001101100 11001100110 10010011000 10010001100 10001001100
    10011001000 10011000100 10001100100 11001001000 11001000100 11000100100
    10110011100 10011011100 10011001110 10111001100 10011101100 10011100110
    11001110010 11001011100 11001001110 11011100100 11001110100 11101101110
    11101001100 11100101100 11100100110 11101100100 11100110100 11100110010
    11011011000 11011000110 11000110110 10100011000 10001011000 10001000110
    10110001000 10001101000 10001100010 11010001000 11000101000 11000100010
    10110111000 10110001110 10001101110 10111011000 10111000110 10001110110
    11101110110 11010001110 11000101110 11011101000 11011100010 11011101110
    11101011000 11101000110 11100010110 11101101000 11101100010 11100011010
    11101111010 11001000010 11110001010 10100110000 10100001100 10010110000
    10010000110 10000101100 10000100110 10110010000 10110000100 10011010000
    10011000010 10000110100 10000110010 11000010010 11001010000 11110111010
    11000010100 10001111010 10100111100 10010111100 10010011110 10111100100
    10011110100 10011110010 11110100100 11110010100 11110010010 11011011110
    11011110110 11110110110 10101111000 10100011110 10001011110 10111101000
    10111100010 11110101000 11110100010 10111011110 10111101110 11101011110
    11110101110 11010000100 11010010000 11010011100 1100011101011'''.split()

def code128_img(s, height=100, bar_width=1):
    ''' Generate a Code 128 barcode image.
        Coded for https://stackoverflow.com/q/52968042/5987
    '''
    codes = code128_codes(s)
    pattern = ''.join(_code128_patterns[c] for c in codes)
    pattern = '00000000000' + pattern + '00000000000'
    width = bar_width * len(pattern)
    color, bg = (0, 0, 0), (255, 255, 255)
    im = Image.new('RGB', (width, height), bg)
    ld = im.load()
    for i, bar in enumerate(pattern):
        if bar == '1':
            for y in range(height):
                for x in range(i * bar_width, (i + 1) * bar_width):
                    ld[x, y] = color
    return im

>>> im = code128_img('AM-H-10-01-1')
>>> im.save(r'c:\temp\temp.pdf')
0 голосов
/ 24 октября 2018

Сэм,

Во-первых, ваш штрих-код не будет сканироваться, как есть.Строка требует добавления начального символа, контрольной суммы и символа остановки для Code128B.Итак, вот что.

enter image description here

Я рекомендую перейти на шрифт Code 39 (который не требует контрольной суммы, а символы начала и окончания одинаковы: "*") или написание кода для создания контрольной суммы и немного больше узнать о Code 128 на Code 128 Wiki .

Во-вторых, я подозреваю, что существуют проблемы с ограничивающей рамкой дляграфика при конвертации в PDF.Эта небольшая часть преобразуемого штрих-кода больше похожа на часть числа девять в строке.Я подозреваю, что происходит некоторое сокращение изображения.enter image description here

Попробуйте заменить обычный текстовый шрифт, чтобы убедиться, что изображение штрих-кода не теряется при конвертации.

Отредактированный ответ, включающий предложение использовать PNGвместо PDF.

Мне удалось заставить программное обеспечение работать, если вы выводите в формате PNG.Я знаю, теперь проблема заключается в том, как конвертировать PNG в PDF.Вы можете начать с изучения некоторых библиотек, упомянутых здесь: Создать PDF из списка изображений

Короче я рекомендую вам создавать графические файлы, а затем вставлять их в файлы документов.

Я также добавил код, необходимый для построения штрих-кода с символами начала, контрольной суммы и остановки:

import os

import matplotlib.pyplot as plt

from matplotlib import font_manager as fm

def draw_label(label, label_dimensions_x=3.8189, label_dimensions_y=1.41732):

    # import barcode code128 font
    fpath = os.path.join("./", "code128.ttf")

    prop = fm.FontProperties(fname=fpath, size=32)

    fig, ax = plt.subplots(1, figsize=(label_dimensions_x,
                                       label_dimensions_y))

    plt.axis('off')
    plt.xticks([], [])
    plt.yticks([], [])
    plt.tight_layout()
    plt.xlim(0, label_dimensions_x)
    plt.ylim(0, label_dimensions_y)

    # calc checksum THEN plot barcode
    weight = 1
    chksum = 104
    for x in label:
        chksum = chksum + weight*(ord(x)-32)
        weight = weight + 1
    chksum = chksum % 103
    chkchar = chr(chksum+32)
    label128 = "%s%s%s%s" % ('Ñ', label, chkchar, 'Ó')
    plt.text(label_dimensions_x / 2, label_dimensions_y / 2, label128,
             ha='center', va='bottom',
             fontproperties=prop)
    try:
        plt.savefig(os.path.join("./", label + '.png'))
    except PermissionError:
        logging.warning("Close the current label pdf's before running this script.")

    return

draw_label('123456789')
draw_label('987654321')
draw_label('Test&Show')

...