Штрих-код печати отображается в окне графика иначе, чем в сохраненном.pdf
У меня возникли проблемы с сохранением моего 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'), текст не обрезается, посмотрите это. Признаюсь, это не красиво и не очень хорошо, но все же должно быть читаемым.
2 ответа
Сэм,
Во-первых, ваш штрих-код не будет сканироваться, как есть. Строка требует добавления начального символа, контрольной суммы и символа остановки для Code128B. Итак, это так.
Я рекомендую изменить шрифт Code 39 (который не требует контрольной суммы, а символы начала и окончания одинаковы: "*") или написать код для получения контрольной суммы и узнать немного больше о Code 128 в Code 128 Wiki.
Во-вторых, я подозреваю, что во время преобразования в PDF существуют проблемы с ограничительной рамкой для графики. Эта небольшая часть преобразуемого штрих-кода больше похожа на часть числа девять в строке. Я подозреваю, что происходит некоторое отсечение изображения.
Попробуйте заменить обычный текстовый шрифт, чтобы убедиться, что изображение штрих-кода не теряется при конвертации.
Отредактированный ответ включает предложение использовать PNG вместо PDF.
Мне удалось заставить программное обеспечение работать, если вы выводите в формате PNG. Я знаю, теперь проблема заключается в том, как конвертировать PNG в PDF. Вы можете начать с изучения некоторых библиотек, упомянутых здесь: Создание PDF из списка изображений
Короче говоря, я рекомендую вам создавать графические файлы, а затем вставлять их в файлы документов.
Я также добавил код, необходимый для построения штрих-кода с символами начала, контрольной суммы и остановки:
импорт ОС импортировать matplotlib.pyplot как plt из matplotlib импортируйте font_manager как фм def draw_label(label, label_dimensions_x=3.8189, label_dimensions_y=1.41732): # импорт шрифта штрих-кода code128 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('выключено') plt.xticks([], []) plt.yticks([], []) plt.tight_layout() plt.xlim(0, label_dimensions_x) plt.ylim(0, label_dimensions_y) # контрольная сумма THEN, штрих-код участка вес = 1 chksum = 104 для х в метке: chksum = chksum + вес *(ord(x)-32) вес = вес + 1 chksum = chksum % 103 chkchar = chr(chksum+32) label128 = "%s%s%s%s" % ('С', метка, chkchar, 'Ó') plt.text(label_dimensions_x / 2, label_dimensions_y / 2, label128, ха = "центр", ва = "низ", fontproperties= проп) пытаться: plt.savefig(os.path.join("./", label + '.png')) кроме PermissionError: logging.warning("Закройте текущие pdf-метки перед запуском этого скрипта.") вернуть draw_label('123456789') draw_label('987654321') draw_label('Test&Show')
Вы слишком усложняете вещи, используя 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://stackru.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://stackru.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')