Как исправить кривой и размытый шрифт при печати штрихкода стандартной компонентой 1С (Native API)?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке и настройке торговых решений на платформе 1С:Предприятие разработчики часто сталкиваются с необходимостью вывода штрихкодов на печать. Стандартным инструментом для этого является компонента «1С:Печать штрихкодов» (Native API), поставляемая в составе Библиотеки стандартных подсистем (БСП) или Библиотеки подключаемого оборудования (БПО). Однако при стандартном подходе к выводу штрихкода подпись под ним (цифры или символы кода) очень часто отображается крайне некачественно: шрифт выглядит рваным, размытым, пикселизированным или «грязным». Это не только портит визуальный вид этикетки или документа, но и может приводить к проблемам со считыванием штрихкода сканером.

В этой статье мы подробно разберем природу данной проблемы, выясним, почему стандартный механизм рендеринга дает такой сбой, и рассмотрим несколько эффективных способов решения — от простых «лайфхаков» с масштабированием до профессиональных методов разделения слоев печати и использования векторной графики.

Почему возникает проблема: анализируем физику процесса

Прежде чем перейти к исправлению кода, давайте проанализируем, почему стандартная компонента Native API выдает «кривой» шрифт. Причины кроются во внутренних механизмах работы платформы 1С и самой компоненты:

  1. Растровый формат вывода: Компонента генерирует конечное изображение штрихкода в растровом формате (обычно PNG). При формировании картинки небольшого физического размера (например, 250 на 40 пикселей) внутренний движок компоненты пытается уместить символы шрифта в очень мелкую пиксельную сетку. Так как полноценное сглаживание (антиалиасинг) на таких масштабах не применяется, шрифты отрисовываются «пиксель в пиксель», из-за чего буквы и цифры приобретают рваный вид.
  2. Влияние экранного масштабирования и DPI принтера: Ситуация катастрофически ухудшается, когда полученная мелкая растровая картинка выводится на печать на специализированный принтер этикеток (с разрешением 200 или 300 DPI) или отображается на экране с системным масштабированием Windows (125%, 150% и более). Операционная система или драйвер принтера пытаются «растянуть» мелкую картинку до нужного физического размера, что приводит к размытию краев штрихов и превращению цифр подписи в нечитаемое пятно.

Выяснив причину дефекта, рассмотрим рабочие варианты его устранения.

Способ 1. Кратное увеличение разрешения картинки (Метод масштабирования)

Рассмотрим самый быстрый программный способ, который позволяет исправить ситуацию без изменения структуры макета табличного документа. Суть метода заключается в обмане механизма рендеринга компоненты: мы заставляем её генерировать картинку в огромном разрешении (например, в 10 раз больше требуемого), а затем средствами платформы 1С сжимаем ее до размеров области макета с включенным свойством пропорционального сжатия.

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

Разберем реализацию этого метода по шагам на примере кода:


Процедура ЗаполнитьРисунокШтрихкодомМасштабирование(Рисунок, ШтрихКод, ТипКода = Неопределено)
    
    // Определяем коэффициенты пересчета пикселей в миллиметры на основе эталонного макета
    Эталон = ПолучитьОбщийМакет("МакетДляОпределенияКоэффициентовЕдиницИзмерения");
    КоличествоМиллиметровВПикселеВысота = Эталон.Рисунки.Квадрат100Пикселей.Высота / 100;
    КоличествоМиллиметровВПикселеШирина = Эталон.Рисунки.Квадрат100Пикселей.Ширина / 100;
    
    // Вычисляем базовый размер штрихкода в пикселях под размер рисунка на макете
    БазоваяШирина = Окр(Рисунок.Ширина / КоличествоМиллиметровВПикселеШирина);
    БазоваяВысота = Окр(Рисунок.Высота / КоличествоМиллиметровВПикселеВысота);
    
    // Вводим коэффициент масштабирования (увеличиваем разрешение в 10 раз)
    КоэффициентМасштаба = 10;
    ШиринаШтрихкода = БазоваяШирина * КоэффициентМасштаба;
    ВысотаШтрихкода = БазоваяВысота * КоэффициентМасштаба;
    
    // Заполняем параметры генерации штрихкода
    ПараметрыШтрихкода = Новый Структура;
    ПараметрыШтрихкода.Вставить("Ширина"            , ШиринаШтрихкода);
    ПараметрыШтрихкода.Вставить("Высота"            , ВысотаШтрихкода);
    ПараметрыШтрихкода.Вставить("ТипКода"           , ?(ЗначениеЗаполнено(ТипКода), ТипКода, 1)); // 1 - это EAN13 по умолчанию
    ПараметрыШтрихкода.Вставить("ОтображатьТекст"   , Истина);
    
    // Размер шрифта также пропорционально увеличиваем в 10 раз
    ПараметрыШтрихкода.Вставить("РазмерШрифта"      , 10 * КоэффициентМасштаба); 
    ПараметрыШтрихкода.Вставить("МонохромныйШрифт"  , Ложь);
    ПараметрыШтрихкода.Вставить("УголПоворота"      , 0);
    ПараметрыШтрихкода.Вставить("Штрихкод"          , ШтрихКод);
    ПараметрыШтрихкода.Вставить("ПрозрачныйФон"     , Истина);
    ПараметрыШтрихкода.Вставить("УровеньКоррекцииQR", 1);
    ПараметрыШтрихкода.Вставить("Масштабировать"    , Ложь);
    ПараметрыШтрихкода.Вставить("СохранятьПропорции", Ложь);
    ПараметрыШтрихкода.Вставить("ВертикальноеВыравнивание", 3); // Выравнивание по нижнему краю
    
    // Получаем качественную картинку высокого разрешения из компоненты БПО
    Рисунок.Картинка = МенеджерОборудованияВызовСервера.ПолучитьКартинкуШтрихкода(ПараметрыШтрихкода);
    
    // ВАЖНО: Устанавливаем режим размера картинки "Пропорционально"
    // Это заставит платформу качественно сжать большую картинку под физический размер рисунка на форме/макете
    Рисунок.РазмерКартинки = РазмерКартинки.Пропорционально;

КонецПроцедуры

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

Способ 2. Разделение штрихкода и текста (Самый надежный и профессиональный метод)

Несмотря на то, что метод масштабирования отлично справляется с задачей улучшения картинки, у него остается концептуальный минус: текст под штрихкодом все равно выводится в виде растрового изображения. При печати на термотрансферных принтерах этикеток с низким разрешением (например, 203 DPI) даже масштабированный растровый текст может слегка подплывать.

Наиболее надежным, профессиональным и «чистым» решением является разделение вывода штрихов кода и текстовой подписи:

  1. В макете табличного документа под рисунком штрихкода добавляем текстовую область (ячейку или текстовое поле).
  2. Настраиваем параметры генерации картинки так, чтобы компонента выводила исключительно штрихи без подписи. Для этого свойству ОтображатьТекст (или ShowText в некоторых версиях компоненты) присваиваем значение Ложь.
  3. Значение штрихкода выводим в подготовленную текстовую ячейку табличного документа стандартными средствами 1С.

Рассмотрим, как меняются параметры генерации штрихкода при таком подходе:


ПараметрыШтрихкода = Новый Структура;
ПараметрыШтрихкода.Вставить("Ширина"          , ШиринаШтрихкода);
ПараметрыШтрихкода.Вставить("Высота"          , ВысотаШтрихкода);
ПараметрыШтрихкода.Вставить("ТипКода"         , ТипКода);
ПараметрыШтрихкода.Вставить("ОтображатьТекст" , Ложь); // Отключаем вывод текста компонентой
ПараметрыШтрихкода.Вставить("Штрихкод"         , ШтрихКод);
ПараметрыШтрихкода.Вставить("ПрозрачныйФон"   , Истина);

Рисунок.Картинка = МенеджерОборудованияВызовСервера.ПолучитьКартинкуШтрихкода(ПараметрыШтрихкода);

В макете табличного документа под рисунком штрихкода объединяем ячейки, задаем для них качественный системный векторный шрифт платформы (например, Arial или Tahoma), устанавливаем нужный размер (например, 9pt) и центрирование. При выводе области макета заполняем текстовый параметр значением штрихкода.

Преимущества метода:

Способ 3. Борьба с отсутствием шрифтов в операционной системе (Особенно актуально для Linux)

Часто проблема «корявого» или «дефолтного» шрифта компоненты обостряется при переносе базы 1С на сервер под управлением Linux (например, CentOS, Ubuntu или Debian). Стандартная компонента Native API при формировании картинки пытается найти в системе качественные шрифты (по умолчанию она ищет шрифт Arial или Tahoma). Если эти шрифты отсутствуют в системе, компонента без предупреждения переключается на самый примитивный растровый шрифт, доступный в ядре ОС, что приводит к ужасному качеству отображения.

Чтобы решить эту проблему на серверах Linux, выполним следующие шаги:

  1. Установим пакет шрифтов Microsoft TrueType core fonts в операционную систему сервера. Для дистрибутивов на базе RedHat/CentOS это делается командой yum install msttcore-fonts-installer, для Debian/Ubuntu — apt-get install ttf-mscorefonts-installer.
  2. В коде формирования штрихкода проверим доступность шрифтов и явно укажем компоненте использовать установленный качественный шрифт:

// Пример программного обхода доступных шрифтов компоненты
Если КомпонентаПечати.НайтиШрифт("Arial") Тогда
    ПараметрыШтрихкода.Вставить("Шрифт", "Arial");
ИначеЕсли КомпонентаПечати.КоличествоШрифтов > 0 Тогда
    // Если Arial не найден, принудительно берем первый доступный качественный векторный шрифт системы
    ПервыйДоступныйШрифт = КомпонентаПечати.ШрифтПоИндексу(0);
    ПараметрыШтрихкода.Вставить("Шрифт", ПервыйДоступныйШрифт);
КонецЕсли;

Способ 4. Использование специализированных TrueType шрифтов (Векторный метод)

Если вы хотите полностью отказаться от внешних компонент генерации картинок (которые могут нестабильно инициализироваться в разных режимах работы платформы, например, на x64-серверах или в веб-клиенте), можно использовать альтернативный метод — специализированные TrueType-шрифты штрихкодов.

Суть метода заключается в следующем:

  1. В операционную систему пользователей и сервера устанавливается специальный шрифт (например, EanGnivc для штрихкодов EAN или IDAutomation). Этот шрифт сопоставляет цифрам и специальным символам графические изображения штрихов.
  2. В модуле 1С пишется несложная функция, преобразующая обычную строку цифр штрихкода в специальную последовательность символов (для формирования стартовых/стоповых линий и расчета контрольного символа).
  3. Полученная закодированная строка выводится в обычную ячейку табличного документа, для которой выбран установленный шрифт штрихкода.

Посмотрим на пример функции подготовки строки для шрифта EanGnivc:


Функция СформироватьСтрокуДляШрифтаEAN13(Знач ИсходныйШтрихкод) Экспорт
    
    // Алгоритм преобразует 13 цифр EAN-13 в специальный набор символов,
    // учитывая левую и правую части кода, а также контрольный символ
    // Для каждого типа шрифта используется своя спецификация кодирования.
    
    Если СтрДлина(ИсходныйШтрихкод) <> 13 Тогда
        Возврат ИсходныйШтрихкод;
    КонецЕсли;
    
    // Кодирование первой цифры
    Результат = Сред(ИсходныйШтрихкод, 1, 1); 
    
    // Логика формирования символов для левой части (символы 2-7) и правой части (символы 8-13)
    // ...
    // В данном примере опускаем полную математическую реализацию расчета контрольного числа
    
    Возврат Результат;
КонецФункции

При таком подходе и штрихкод, и текст под ним являются 100% векторными текстовыми объектами платформы 1С. Они масштабируются абсолютно без потери качества, весят ничтожно мало и печатаются идеально четко на любом принтере с любым разрешением DPI.

Резюме и рекомендации

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

Для быстрого исправления «здесь и сейчас» рекомендуем применить Способ 1 (масштабирование картинки в 10 раз с пропорциональным сжатием). Он требует изменения всего нескольких строк кода в процедуре формирования рисунка штрихкода.

Если же вы разрабатываете тиражное решение или стремитесь к максимальному качеству печати на специализированных принтерах этикеток, лучшим выбором будет Способ 2 (разделение вывода штрихов и текста подписи). Этот вариант гарантирует безупречную четкость шрифта и исключает любые проблемы со считыванием кодов на кассовых узлах и складах.

← На главную