Как в DataMatrix помещаются такие длинные строки? Разбор механизмов сжатия и кодирования

Программист IT и автоматизация бизнеса
← На главную

При внедрении маркировки «Честный ЗНАК» (для табака, лекарств, обуви и других товарных групп) разработчики 1С часто сталкиваются с удивительным фактом. Двумерный штрихкод DataMatrix ECC 200 на пачке сигарет имеет физический размер всего 24x24 модуля (точек). При этом в него умудряются упаковать длинную текстовую строку, содержащую GTIN (14 цифр), индивидуальный серийный номер, а также криптографический хвост (код проверки).

Если попытаться посчитать емкость такого штрихкода «в лоб», то возникает математическое недоумение. Кажется, что 576 точек (24 умножить на 24) физически не могут вместить в себя столько информации, ведь стандартный символ ASCII требует 8 бит (или хотя бы 7 бит в усеченном варианте). В этой статье мы подробно разберем, какой сложный математический аппарат и какие механизмы сжатия данных позволяют упаковывать длинные строки в миниатюрные матрицы, и как это работает на практике.

Анатомия матрицы 24x24: сколько места доступно на самом деле?

Для начала проанализируем структуру матрицы размером 24x24 модуля. Общее количество точек в ней действительно составляет 576. Однако мы не можем использовать их все для записи полезных данных. Часть пространства уходит на служебные элементы, необходимые сканеру для распознавания штрихкода в пространстве:

  1. Шаблон поиска (Finder Pattern): Слева и снизу штрихкода расположена сплошная черная рамка в виде угла (буквы «L»). Она помогает сканеру определить ориентацию кода и угол наклона при чтении.
  2. Шаблон синхронизации (Timing Pattern): Сверху и справа расположена чередующаяся черно-белая линия. Она сообщает сканеру физический размер одного модуля (точки) и плотность матрицы.

Эти служебные линии «забирают» внешние ряды и колонки. В итоге для хранения самих данных и кодов исправления ошибок остается внутренняя полезная область размером 22x22 модуля, что дает нам ровно 484 точки.

В терминологии стандарта DataMatrix ECC 200 базовой единицей информации является кодовое слово (codeword), которое состоит из 8 бит (модулей). Физическая емкость полезной области кода размером 24x24 составляет 72 кодовых слова. Из них:

Таким образом, наша задача сводится к следующему: выяснить, как алгоритмы DataMatrix умудряются упаковать строку длиной в 30, 40 или даже более символов всего в 52 байта (кодовых слова).

Высокоуровневое кодирование: алгоритмы эффективного сжатия

Основной секрет невероятной емкости DataMatrix заключается в использовании схем (режимов) кодирования данных (encoding modes). Стандарт ECC 200 поддерживает 6 различных режимов работы. Самое интересное заключается в том, что генератор штрихкода может переключаться между этими режимами прямо «на лету» в процессе формирования одной и той же матрицы, выбирая наиболее экономичный способ представления для каждого участка строки.

Рассмотрим подробнее основные режимы, которые позволяют эффективно сжимать информацию.

1. Режим ASCII (Базовый со сжатием цифр)

Этот режим активен по умолчанию в начале кодирования. Обычные текстовые символы (латиница, знаки препинания) кодируются стандартным образом — 1 символ занимает 1 кодовое слово (8 бит). Однако для цифровых последовательностей в режиме ASCII предусмотрено двойное сжатие.

Если алгоритм обнаруживает в строке две цифры подряд (например, "45"), он не кодирует их как два отдельных символа. Вместо этого пара цифр преобразуется в одно числовое значение по формуле:

Кодовое слово = Числовое значение пары + 130

Для пары цифр "45" кодовое слово будет равно: 45 + 130 = 175. Таким образом, вместо двух байт на две цифры тратится всего 1 байт. Это позволяет сократить объем, требуемый для записи числовых данных (таких как GTIN), ровно в два раза!

2. Режимы C40 и Text (Упаковка текста)

Режим C40 оптимизирован для эффективного кодирования заглавных латинских букв, цифр и некоторых спецсимволов. Именно эти символы чаще всего составляют основу серийных номеров и криптографических ключей в маркировке.

Режим Text работает аналогично, но он оптимизирован под строчные (маленькие) латинские буквы.

В этих режимах используется специальная 40-ричная система счисления. Алгоритм берет три символа из входящей строки и упаковывает их всего в два кодовых слова (16 бит). Математически это реализуется по следующей формуле:

V = (1600 × C1) + (40 × C2) + C3 + 1

Где C1, C2 и C3 — это внутренние коды символов в 40-ричной таблице (значения от 0 до 39). Полученное число V (которое не превышает 64000) затем раскладывается на два байта. Использование режимов C40 и Text дает чистую экономию пространства в 33% по сравнению со стандартным кодированием ASCII.

3. Режим EDIFACT

Этот режим применяется реже, но он крайне эффективен, если строка состоит исключительно из символов ASCII с кодами от 32 до 94 (заглавные буквы, цифры, основные знаки препинания). Он позволяет упаковать четыре символа в три кодовых слова, выделяя на каждый символ ровно по 6 бит информации.

4. Режим Base 256

Используется для записи чистых двоичных данных (например, зашифрованных бинарных блоков), где текстовое сжатие неприменимо. В этом режиме данные записываются «как есть», без оптимизации.

Разбираем реальный пример: код маркировки «Честный ЗНАК»

Давайте проанализируем, как эти алгоритмы работают на практике при формировании кода маркировки для пачки сигарет. Типичный код маркировки (после извлечения транспортных префиксов) представляет собой строку следующего вида:

010460000000000021xxxxx93xxxx

Где:

Давайте пошагово проследим, как генератор DataMatrix упакует эту информацию в матрицу 24x24:

  1. Кодирование GTIN: Генератор видит последовательность цифр. Включается режим ASCII со сжатием пар цифр. Идентификаторы применения и 14 цифр GTIN преобразуются в пары. На кодирование GTIN и служебного префиксового символа FNC1 уходит всего около 8–9 байт вместо 16!
  2. Кодирование серийного номера: Как только начинаются буквенно-цифровые символы серийного номера, генератор вставляет специальный переключающий управляющий код и переходит в режим C40. Серийный номер из 7 символов упаковывается по схеме «3 символа в 2 байта». На это тратится всего 5 байт.
  3. Кодирование криптохвоста: Код проверки (криптохвост) также состоит из букв и цифр. Он кодируется в режиме C40, занимая еще около 3–4 байт.

В результате вся длинная исходная строка, которая в текстовом виде (с учетом разделителей групп GS / ASCII 29) занимает около 35–40 символов, физически сжимается всего до 25–30 кодовых слов!

Это значение с запасом укладывается в лимит 52 кодовых слов данных, доступных в матрице 24x24. Более того, у нас остается свободное место для заполнения пустыми байтами-заполнителями (pad characters), если строка оказалась короче максимальной емкости.

Защита от повреждений: избыточность Рида-Соломона

Выяснив, как данные сжимаются, мы не должны забывать о надежности. Если пачка сигарет помнется в кармане или код частично сотрется при транспортировке, он все равно должен уверенно считаться на кассе. За это отвечает алгоритм коррекции ошибок Рида-Соломона (ECC 200).

Как мы уже выяснили, в матрице 24x24 под коды коррекции ошибок выделено целых 20 кодовых слов из 72. Это очень мощная математическая защита. Алгоритм Рида-Соломона строит специальный избыточный полином на основе полезных данных. При сканировании поврежденного кода математический аппарат восстанавливает утраченные биты.

Благодаря этому DataMatrix ECC 200 гарантирует успешное чтение информации даже в том случае, если до 30% площади штрихкода физически уничтожено или затерто. Это критически важно для розничной торговли, где скорость обслуживания на кассе напрямую зависит от качества считывания маркировки.

Особенности работы с DataMatrix в среде 1С

При разработке и поддержке решений на платформе 1С программисту редко приходится реализовывать алгоритмы низкоуровневого сжатия DataMatrix вручную. В современных конфигурациях эта задача полностью возложена на специализированные компоненты печати штрихкодов.

Рассмотрим пример того, как правильно подготовить строку маркировки для генерации корректного штрихкода GS1 DataMatrix в среде 1С. Для того чтобы сжатие отработало максимально эффективно, крайне важно правильно передавать управляющие символы, в частности разделитель групп GS (ASCII 29):


// Функция подготавливает валидную строку для генератора GS1 DataMatrix
Функция ПодготовитьСтрокуМаркировкиДляПечати(Знач GTIN, Знач СерийныйНомер, Знач КодПроверки) Экспорт
    
    // Символ разделителя GS (ASCII 29) обязателен по стандарту GS1
    // Он указывает сканеру и оптимизатору на разделение полей переменной длины
    СимволGS = Символ(29); 
    
    // Формируем стандартизированную строку с идентификаторами применения (AI)
    // AI "01" - это GTIN (всегда 14 символов, фиксированная длина)
    // AI "21" - это серийный номер (переменная длина, требует разделителя в конце)
    // AI "93" - это код проверки (криптохвост)
    
    СтрокаМаркировки = "01" + GTIN + "21" + СерийныйНомер + СимволGS + "93" + КодПроверки;
    
    Возврат СтрокаМаркировки;
КонецФункции

Когда эта подготовленная строка передается во внешнюю компоненту печати штрихкодов 1С (например, КомпонентаПечатиШтрихкодов, входящую в состав БиблиотекиСтандартныхПодсистем), компонента автоматически анализирует переданную последовательность. Она распознает цифровые блоки, встречает символ GS, своевременно переключает внутренние режимы кодирования между ASCII и C40, генерирует избыточные коды Рида-Соломона и на выходе выдает идеально оптимизированную картинку DataMatrix размером 24x24 модуля.

Если же программист проигнорирует требования стандартов (например, забудет вставить символ разделителя GS или передаст данные в неверном формате), оптимизатор компоненты не сможет применить алгоритмы эффективного сжатия C40. В результате строка либо не поместится в матрицу заданного размера, либо сгенерированный штрихкод будет иметь избыточный размер (например, 32x32 или 36x36), что сделает невозможным его печать на маленьком стикере или пачке.

← На главную