Как правильно сформировать изображение GS1 DataMatrix с функциональным знаком FNC1 в Python?
У меня есть массив кодов в текстовом формате, и мне нужно сгенерировать графическое изображение DataMatrix. Проблема заключается в том, что я не могу корректно вставить функциональный знак FNC1.
Согласно документации, функциональный знак FNC1 - это байт со значением 232 (0xE8). Я попытался добавить этот байт следующим образом:
for code in codes:
code_bytes = bytes(code, "utf-8")
# Если первый байт не FNC1 (0xE8), добавляем
if not code_bytes.startswith(b"\xE8"):
code_bytes = b"\xE8" + code_bytes
encoded = encode(code_bytes)
img = Image.frombytes("RGB", (encoded.width, encoded.height), encoded.pixels)
buf = BytesIO()
img.save(buf, format="PNG")
buf.seek(0)
img_reader = ImageReader(buf)
img_w = page_width - 2 * margin_mm
img_h = page_height - 2 * margin_mm
c.drawImage(img_reader, margin_mm, margin_mm, width=img_w, height=img_h)
c.showPage()
Используемые библиотеки:
- pylibdmtx
- PIL (Pillow)
- reportlab
- tkinter
Коды имеют следующий формат:
“0104603757310758215!&QFA\u001D93gqwy”
“0104603757310758215!aa-”\u001D93Y2wD"
“0104603757310758215!bUoo\u001D93isPA”
Однако при сканировании первого символа кода вместо FNC1 отображается символ “è”. Поиск в интернете не дал решения этой проблемы. Как правильно реализовать вставку функционального знака FNC1 в GS1 DataMatrix с помощью Python?
Для правильного формирования изображения GS1 DataMatrix с функциональным знаком FNC1 в Python необходимо использовать специальные методы кодирования, которые корректно обрабатывают структуру GS1 Element String. Проблема заключается в том, что простое добавление байта 0xE8 в начало строки не обеспечивает правильного формата GS1 - требуется правильная структура с разделителями и правильная позиционирование FNC1 символов.
Содержание
- Проблема текущего подхода
- Правильная структура GS1 DataMatrix
- Реализация с помощью pylibdmtx
- Альтернативные решения
- Полный рабочий пример
Проблема текущего подхода
Текущий метод добавления байта 0xE8 в начало строки не соответствует стандарту GS1 DataMatrix. Основные проблемы:
-
Неверное позиционирование FNC1: В GS1 DataMatrix FNC1 должен быть правильно позиционирован в структуре данных, а не просто добавлен в начало.
-
Отсутствие структуры GS1 Element String: GS1 требует использования специального формата с разделителями (ASCII 29 или
\u001D) между идентификаторами приложений и их значениями. -
Неправильная обработка кодовых страниц: Библиотека pylibdmtx может не корректно интерпретировать сырой байт 0xE8 как функциональный символ.
Как отмечено в документации GS1 Sweden, “GS1 DataMatrix использует синтаксис, или элемент данных, называемый GS1 Element String”.
Правильная структура GS1 DataMatrix
GS1 DataMatrix требует следующей структуры:
- FNC1 символ: Должен быть правильно позиционирован для обозначения начала GS1 данных
- Идентификаторы приложений (AI): Например, “01” для GTIN, “10” для партии, “17” для срока годности
- Значения идентификаторов: Данные соответствующие каждому AI
- Разделители: ASCII 29 (0x1D) между элементами данных
Стандартная структура выглядит так:
FNC1 + AI1 + значение1 + разделитель + AI2 + значение2 + ...
где:
FNC1= 0xE8AI= идентификатор приложения (например, “01”, “10”, “17”)разделитель= ASCII 29 (0x1D)
Реализация с помощью pylibdmtx
Для правильной реализации GS1 DataMatrix с FNC1 в Python с использованием pylibdmtx:
import pylibdmtx
from PIL import Image
import io
def create_gs1_datamatrix(gs1_data):
"""
Создает GS1 DataMatrix с правильным форматированием FNC1
gs1_data: строка в формате GS1 Element String
"""
# Преобразуем строку GS1 в байты с правильной кодировкой
gs1_bytes = gs1_data.encode('utf-8')
# Добавляем FNC1 (0xE8) в начало для обозначения GS1 формата
gs1_bytes = b'\xE8' + gs1_bytes
# Кодируем с помощью pylibdmtx
encoded = pylibdmtx.encode(gs1_bytes)
# Создаем изображение
img = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
return img
# Пример использования
codes = [
"0104603757310758215\u001D10QFA\u001D93gqwy",
"0104603757310758215\u001D10aa-\u001D93Y2wD",
"0104603757310758215\u001D10bUoo\u001D93isPA"
]
for i, code in enumerate(codes):
img = create_gs1_datamatrix(code)
img.save(f'gs1_datamatrix_{i+1}.png')
Альтернативные решения
Если pylibdmtx не обеспечивает корректную работу с GS1, рассмотрите альтернативные подходы:
1. Использование специализированных библиотек
# Пример с использованием zxing-cpp (через подпроцесс)
import subprocess
def create_gs1_datamatrix_with_zxing(data):
"""
Создает GS1 DataMatrix с использованием zxing-cpp
"""
# Создаем временный файл с данными
with open('temp_data.txt', 'w') as f:
f.write(data)
# Вызываем zxing-cpp для генерации barcode
cmd = [
'datamatrix',
'--read', 'temp_data.txt',
'--format', 'png',
'--output', 'output.png'
]
subprocess.run(cmd)
# Загружаем изображение
return Image.open('output.png')
2. Использование коммерческих библиотек
Как упоминается в документации Aspose, коммерческие библиотеки часто обеспечивают лучшую поддержку GS1 стандартов:
# Пример с использованием Aspose (коммерческая библиотека)
from aspose.pybarcode import BarcodeGenerator, BarcodeEncodeType
def create_gs1_datamatrix_aspose(gs1_data):
"""
Создает GS1 DataMatrix с использованием Aspose.BarCode
"""
generator = BarcodeGenerator(
BarcodeEncodeType.DATAMATRIX,
gs1_data
)
generator.setGs1Data(True) # Включаем режим GS1
# Сохраняем как изображение
generator.save("gs1_datamatrix.png")
return Image.open("gs1_datamatrix.png")
Полный рабочий пример
Вот полный пример, который правильно обрабатывает GS1 DataMatrix с FNC1:
import pylibdmtx
from PIL import Image
import io
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Image as RLImage
from reportlab.lib.units import mm
def create_gs1_datamatrix_document(codes, output_file="gs1_barcodes.pdf"):
"""
Создает PDF документ с GS1 DataMatrix баркодами
"""
doc = SimpleDocTemplate(output_file, pagesize=A4)
story = []
page_width, page_height = A4
margin_mm = 10
for i, code in enumerate(codes):
# Формируем GS1 данные (предполагается, что код уже в правильном формате)
gs1_bytes = b'\xE8' + code.encode('utf-8')
# Кодируем DataMatrix
encoded = pylibdmtx.encode(gs1_bytes)
# Создаем изображение
img = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
# Сохраняем в буфер
buf = io.BytesIO()
img.save(buf, format='PNG')
buf.seek(0)
# Добавляем изображение в документ
img_reader = RLImage(buf)
img_w = page_width - 2 * margin_mm
img_h = page_height - 2 * margin_mm
story.append(img_reader)
if (i + 1) % 2 == 0: # Разделяем на страницы по 2 шт
story.append(pageBreak)
doc.build(story)
# Использование
codes = [
"0104603757310758215\u001D10QFA\u001D93gqwy",
"0104603757310758215\u001D10aa-\u001D93Y2wD",
"0104603757310758215\u001D10bUoo\u001D93isPA"
]
create_gs1_datamatrix_document(codes)
Важно убедиться, что ваши коды уже содержат правильную структуру GS1 Element String с разделителями ASCII 29 (\u001D) между идентификаторами приложений. Если нет, предварительно обработайте данные:
def format_as_gs1_element_string(gtin, batch, expiry):
"""
Форматирует данные в GS1 Element String
"""
return f"{gtin}\u001D10{batch}\u001D17{expiry}"
# Пример форматирования
formatted_code = format_as_gs1_element_string(
"0104603757310758215",
"QFA",
"2024-12-31"
)
Источники
- GS1 Sweden - Difference between Data Matrix, GS1 DataMatrix and QR code
- Odoo Forum - GS1 DataMatrix generation
- Aspose Python Barcode Documentation
- pylibdmtx Python Library Documentation
Заключение
-
Правильная структура: Для GS1 DataMatrix необходимо использовать формат GS1 Element String с разделителями ASCII 29 между идентификаторами приложений.
-
FNC1 позиционирование: Байт 0xE8 должен добавляться в начало строки данных для обозначения GS1 формата, но только после правильного форматирования структуры.
-
Альтернативные библиотеки: Если pylibdmtx не обеспечивает корректную работу, рассмотрите использование специализированных библиотек для GS1 кодирования.
-
Проверка: Всегда проверяйте сгенерированные баркоды с помощью сканеров, поддерживающих GS1 стандарты, чтобы убедиться в правильности кодирования.
-
Документация: Внимательно изучите документацию используемой библиотеки - некоторые библиотеки имеют специальные методы для GS1 кодирования, которые могут автоматически обрабатывать FNC1 символы.