Документация разработчика

Создание Датаматрикс

Генерация символов DataMatrix ECC 200 по ГОСТ Р ИСО/МЭК 16022 с проверкой GS1 и профиля «Честного знака» — PNG и JPEG для печати маркировки.

24 размеравсе квадратные символы ГОСТ, от 10×10 до 144×144
0,26 мскод и PNG символа 10×10; 144×144 — 7,3 мс
Версия 1.0

Обзор

Библиотека строит символы DataMatrix ECC 200 по ГОСТ Р ИСО/МЭК 16022 (ISO/IEC 16022) и отдаёт их картинкой PNG или JPEG — в память или в файл. Поддерживаются все 24 квадратных размера, от 10×10 до 144×144, шесть схем кодирования (ASCII, C40, Text, X12, EDIFACT, Base256) и опция GS1 с проверкой строки по GS1 General Specifications и профилю «Честного знака».

Каждый собранный символ библиотека читает обратно сама (самопроверка): рамки, кодовые слова, синдромы Рида–Соломона, разбор схем. Символ, который не прочитался, наружу не отдаётся.

Публичный интерфейс — на C++20, заголовки в include/dmgen/. Публичный API не бросает исключений: всё, что может не получиться, возвращает Result<T>. Для других языков есть плоский C ABI (dmgen_c) — годится для P/Invoke, JNA, cgo и ctypes.

Платформы

Windows x86-64 и Linux x86-64, ARM64 и ARMv7 — библиотека собирается и проверяется в том числе для одноплатных компьютеров вроде Raspberry Pi. Сторонний код встроен в поставку, внешних зависимостей нет.

Подключение

Библиотека приходит уже собранной — собирается только ваша программа, которой нужен компилятор C++20. Статическая libdmgen.a требует той же стандартной библиотеки C++, что и у поставки; если это неудобно, подключайте dmgen_c через C ABI — у неё нет таких требований.

include\dmgen\{Dmgen,Encoder,Gs1,Image,License,Options,Result,Symbol,Version,dmgen_c}.h
lib\libdmgen.a
lib\dmgen_c.dll.a
lib\pkgconfig\dmgen.pc
bin\dmgen_c.dll
bin\dmgen.exe

libdmgen.a собрана MinGW-w64 GCC — MSVC её не слинкует, нужен тот же тулчейн: MSYS2, консоль MINGW64 (не UCRT64), пакеты pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-pkgconf. Строка линковки — из dmgen.pc:

$env:PKG_CONFIG_PATH = "C:\куда\распакован\lib\pkgconfig"
pkg-config --static --cflags --libs dmgen

Системные winhttp, crypt32, shell32 и advapi32 (проверка лицензии) уже прописаны в пакете.

В meson — зависимость по имени пакета:

dmgen_dep = dependency('dmgen', required: true, static: true)
executable('мояпрограмма', 'main.cpp', dependencies: [dmgen_dep])

Быстрый старт

Код «Честного знака» → файл PNG. Всё, что нужно, — один заголовок:

#include <dmgen/Dmgen.h>
#include <iostream>

int main() {
    dmgen::EncodeOptions o;
    o.gs1 = dmgen::Gs1Mode::ChestnyZnak;          // проверка и FNC1 первым словом

    auto sym = dmgen::encode("(01)04601234567893(21)5Abc12Xyz!-(93)dGVz", o);
    if (!sym) {
        std::cerr << sym.error().message << "\n";   // по-русски
        return 1;
    }

    dmgen::RenderOptions r;                        // 8 px на модуль, свободная зона 2
    auto saved = dmgen::save(dmgen::render(sym->modules, r), "code.png", dmgen::ImageFormat::Png);
    return saved ? 0 : 1;
}

Картинка в память — dmgen::toPng(image) или dmgen::toJpeg(image), обе возвращают Result<std::vector<uint8_t>>.

Кодирование

Result<Symbol> encode(std::string_view data, const EncodeOptions& options = {});

Байты 128–255 кодируются через Upper Shift. Текст не перекодируется: строку UTF-8 символ хранит как UTF-8.

EncodeOptions

ПолеПо умолчаниюСмысл
side0Сторона символа: 0 — наименьший подходящий, иначе 10, 12, 14, 16, 18, 20, 22, 24, 26, 32, 36, 40, 44, 48, 52, 64, 72, 80, 88, 96, 104, 120, 132, 144. Не из списка — InvalidArgument, не помещается — SizeTooSmall.
encodationAutoAuto — схемы выбирает предпросмотр приложения P ГОСТ; Minimal — кратчайший поток (дольше считается); либо одна схема: Ascii, C40, Text, X12, Edifact, Base256.
gs1OffOff, Gs1, ChestnyZnak. Строка проверяется до кодирования; нарушение — Gs1Invalid.
separatorGs29Разделитель групп: Gs29 — байт GS, как в «Честном знаке»; Fnc1 — кодовое слово 232 (только в режиме Gs1).
gs1InputAutoRaw — разделитель байтом 0x1D или записью <GS>, {GS}, \x1D; Bracketed — (01)…(21)…, разделители расставятся сами; Auto — по «(» в начале.
verifytrueСамопроверка: собранный символ читается обратно и сравнивается со входом.

Symbol

info — выбранный размер (SymbolInfo), modules — матрица модулей без свободной зоны (BitMatrix, 1 — тёмный), codewords — кодовые слова в порядке размещения, segments — какая схема на каком участке, text — строка, которую вернёт ридер. Таблица размеров — dmgen::squareSizes().

GS1 и «Честный знак»

auto rep = dmgen::gs1::validate("(01)04601234567894(21)ABC", dmgen::Gs1Mode::ChestnyZnak);
for (const auto& i : rep.issues)
    std::cout << (i.warning ? "предупреждение: " : "ошибка: ") << i.message << "\n";
// ошибка: AI (01) GTIN: контрольная цифра 4, должна быть 3
// ошибка: «Честный знак»: нет кода проверки — нужен 93 или пара 91 и 92

Проверяются известность AI, длины и наборы знаков, контрольные цифры GTIN/SSCC/GLN, даты, обязательные разделители после AI без предопределённой длины и повторы AI. Профиль «Честного знака»: 01 первым, 21 вторым, код проверки 93 (4 знака) или 91 (4) + 92 (44 или 88).

Report::normalized — строка ровно в том виде, в каком её вернёт ридер (с байтом GS). Проверка GS1 лицензии не требует.

Картинка

ФункцияЧто делает
render(modules, RenderOptions)Растр Gray8: modulePx (8), quietZone (2; ГОСТ — не меньше 1), invert, dark/light, dpi.
RenderOptions::fromMm(мм, dpi)Модуль в миллиметрах при разрешении печати; DPI пишется в файл (pHYs, JFIF).
RenderOptions::jpegFriendly()Модуль кратен 8 px: блоки 8×8 JPEG однотонные, звона на краях нет.
toPng, toJpeg, savePNG (рекомендуется) или JPEG в память или в файл; путь — std::filesystem::path, Юникод на Windows работает. Качество JPEG ниже 90 для штрихкода не рекомендуется.
auto r = dmgen::RenderOptions::fromMm(0.5, 300);   // модуль 0,5 мм при 300 dpi
dmgen::save(dmgen::render(sym->modules, r), "label.png", dmgen::ImageFormat::Png);

Ошибки

Result<T> — значение или Error с полями code и message (UTF-8, по-русски). Кому удобнее исключения — value() бросает std::runtime_error с текстом ошибки.

ErrorCodeСмысл
InvalidArgumentНеверная опция: размер не из таблицы, пустые данные…
DataTooLongДанные не помещаются даже в 144×144
SizeTooSmallДанные не помещаются в явно заданный размер
UnencodableCharЗнак нельзя закодировать выбранной схемой
Gs1InvalidСтрока не прошла проверку GS1 (подробности — gs1::validate)
IoErrorНе удалось записать файл или изображение
InternalVerifyFailedСамопроверка не прочитала собранный символ — ошибка dmgen
UnlicensedПробный период кончился, лицензии нет

C ABI

Библиотека dmgen_c.dll / libdmgen_c.so, заголовок dmgen_c.h, экспортируются только dmgen_*. Только C-типы фиксированного размера, опции со struct_size, память освобождает dmgen_free; есть вариант с буфером вызывающего — dmgen_make_image_into.

dmgen_options o; dmgen_error e; uint8_t* png; size_t len;
dmgen_options_init(&o);
o.gs1 = DMGEN_GS1_CHESTNY_ZNAK;
if (dmgen_make_image((const uint8_t*)data, n, &o, DMGEN_FORMAT_PNG, &png, &len, &e) == DMGEN_OK) {
    /* … */
    dmgen_free(png);
}

Версия библиотеки

DMGEN_VERSION_STRING — версия заголовков, dmgen::versionString() — версия, с которой собрана библиотека. По расхождению видно, что заголовки и .a от разных сборок.

Лицензия

Библиотека кодирует, пока идёт пробный период (месяц с первого запуска на машине, без сети и регистрации) или действует лицензия. Иначе encode() отвечает ErrorCode::Unlicensed. Проверка GS1 и рисование готовой матрицы лицензии не требуют. Лицензия привязана к оборудованию (материнская плата, процессор, системный диск), а не к установке ОС; пробный период и лицензия не зависят от библиотеки распознавания на той же машине.

#include <dmgen/License.h>

dmgen::LicenseStatus s = dmgen::license::status();
if (!s.canEncode()) std::cerr << s.message;          // «Пробный период закончился. Нужна лицензия»

dmgen::license::activate("XXXXX-XXXXX-XXXXX-XXXXX-XXXXX");   // онлайн
dmgen::license::writeActivationRequest("request.json");        // офлайн: в личный кабинет …
dmgen::license::importLicenseFile("license.lic");              // … и обратно
dmgen::license::deactivate();                                   // переезд на другую машину

deactivate() сдаёт место распиской этой машины. Каждый ответ сервера лицензий привязан к своему запросу: библиотека отправляет случайное одноразовое число, сервер возвращает его в подписанном ответе, и записанный раньше ответ повторно не примется. Расписка тоже одноразовая — в ней номер из последнего полученного от сервера ответа, поэтому расписку из восстановленной копии старого состояния машины сервер не примет; секрет для её подписи сервер выдаёт только при первой активации машины. У лицензий с полной автономией (full) сдача места расходует лимит переносов; когда он исчерпан, перенос делает поддержка.

Основной способ — файл dmgen.key

Положите текстовый файл dmgen.key с ключом рядом с dmgen_c.dll / libdmgen_c.so или с программой. При первом обращении к библиотеке ключ уйдёт на сервер — один раз; дальше лицензия раз в сутки сама сверяется с сервером в фоновом потоке, кодирование сети не ждёт никогда.

Состояния

LicenseStateКодируетСмысл
TrialдаИдёт пробный период
ActiveдаЛицензия действует
RefreshDueдаДавно не было связи с сервером; библиотека сама пробует раз в час
TrialExpiredнетПробный период кончился — нужна лицензия
ExpiredнетОплаченный срок кончился; продление в кабинете подхватится само
NetworkRequiredнетСрок работы без связи вышел — нужна связь с сервером
WrongMachineнетЛицензия выдана другой машине
InvalidнетЗапись лицензии не проходит проверку подписи

Режим автономии задаёт тариф: limited — 7 дней без связи и ещё 7 после предупреждения, extended — 30 + 90, full — в сеть не нужно никогда.

Командная строка

dmgen "0104601234567893215Abc12Xyz!-<GS>93dGVz" --gs1=cz -o code.png
dmgen --check-gs1 --gs1=cz "(01)04601234567893(21)5Abc12Xyz!-(93)dGVz"
dmgen --all-sizes "Hello" --out-dir sizes/
dmgen --batch codes.txt --out-dir out/ --gs1=cz --mm=0.5 --dpi=300

dmgen --license status                # состояние, срок, автономия
dmgen --license activate <ключ>
dmgen --license deactivate            # переезд на другую машину

Ключи: --size=, --scheme=, --separator=, --input=, --px=, --quiet=, --mm= с --dpi=, --invert, --jpeg-friendly, --quality=. Без лицензии утилита завершается с кодом 4.

Нужной функции нет в библиотеке или ваш случай за её границами — доработаем под вашу задачу. Напишите нам →