При работе с базами данных 1С, особенно в торговых конфигурациях с большим каталогом номенклатуры, часто возникает проблема стремительного роста объема информационной базы. Основной источник «тяжелых» данных — это неотптимизированные изображения товаров, загружаемые пользователями напрямую с фотоаппаратов или смартфонов. Картинка разрешением 4000x3000 пикселей может весить более 5-10 МБ, в то время как для отображения в карточке товара или на сайте достаточно разрешения 800x600 пикселей и веса в 100-200 КБ.
В этой статье мы подробно разберем, какими способами можно уменьшить размер картинок и выполнить их обработку непосредственно в системе 1С:Предприятие 8. Мы рассмотрим как современные штатные механизмы платформы, так и альтернативные варианты с привлечением внешних библиотек и инструментов.
Начиная с версии платформы 8.3.14, разработчикам больше не нужно прибегать к сторонним библиотекам или внешним компонентам для элементарных операций с графикой. В системе появился мощный встроенный класс ОбрабатываемаяКартинка. Он позволяет производить операции масштабирования, обрезки, изменения формата и сжатия прямо на стороне сервера 1С.
Давайте разберем по шагам типовую задачу: у нас есть исходная картинка большого размера, сохраненная в справочнике или полученная в виде двоичных данных, и нам нужно уменьшить ее ширину до 800 пикселей с сохранением пропорций, а также перевести в формат JPEG для максимального сжатия.
Проанализируем пример кода, решающий эту задачу:
// Предположим, что ДвоичныеДанныеИсходные — это наши исходные данные файла изображения
ИсходнаяКартинка = Новый Картинка(ДвоичныеДанныеИсходные);
// Инициализируем объект для обработки
Обработка = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
// Определяем текущие размеры, чтобы не увеличивать маленькие картинки случайно
ТекущаяШирина = ИсходнаяКартинка.Ширина();
Если ТекущаяШирина > 800 Тогда
// Устанавливаем ширину 800 пикселей.
// Второй параметр (Высота) передаем как Неопределено — 1С сама рассчитает пропорции!
Обработка.УстановитьРазмер(800, Неопределено);
КонецЕсли;
// Устанавливаем формат JPEG для оптимизации размера файла
Обработка.УстановитьФормат(ФорматКартинки.JPEG);
// Получаем измененную картинку обратно
РезультатКартинка = Обработка.ПолучитьКартинку();
ДвоичныеДанныеРезультата = РезультатКартинка.ПолучитьДвоичныеДанные();
// Теперь ДвоичныеДанныеРезультата можно записать в базу данных или сохранить на диск
Использование этого объекта крайне эффективно, поскольку все вычисления происходят в памяти на сервере без необходимости создавать временные файлы на диске. Помимо простого изменения размера, объект ОбрабатываемаяКартинка предоставляет разработчику следующие возможности:
Масштабировать().Повернуть() позволяет развернуть изображение на 90, 180 или 270 градусов (полезно при загрузке фото со смартфонов, где нарушена ориентация).ПреобразоватьВОттенкиСерого() позволяет обесцветить картинку, что дополнительно уменьшает вес файла.ВыделитьОбласть() кадрирует изображение по заданной прямоугольной рамке.Иногда перед обработкой изображения нам нужно просто узнать его текущие характеристики (разрешение, вес в байтах, формат), чтобы принять решение о необходимости сжатия. В современных версиях платформы 1С базовый объект Картинка оснащен всеми необходимыми свойствами.
Рассмотрим, как можно проанализировать свойства картинки:
ВыбраннаяКартинка = Новый Картинка(ПутьКФайлу);
ШиринаПикс = ВыбраннаяКартинка.Ширина();
ВысотаПикс = ВыбраннаяКартинка.Высота();
РазмерВБайтах = ВыбраннаяКартинка.РазмерФайла();
ГлубинаЦвета = ВыбраннаяКартинка.ГлубинаЦвета();
Если РазмерВБайтах > 1024 * 1024 Тогда // Если файл больше 1 МБ
Сообщить("Файл слишком большой! Размер: " + Округлить(РазмерВБайтах/1024/1024, 2) + " МБ. Требуется сжатие.");
КонецЕсли;
Это избавляет разработчиков от необходимости использовать внешние консольные утилиты вроде ImageMagick только ради того, чтобы узнать физический размер изображения.
Если по каким-то причинам ваша база данных все еще работает на старых релизах платформы (ниже 8.3.14), стандартный объект ОбрабатываемаяКартинка будет недоступен. В таком случае на операционных системах семейства Windows можно использовать встроенную службу работы с изображениями WIA через COM-соединение.
Выясним, как реализовать этот алгоритм на практике:
// Создаем объекты для работы с изображением через COM
Попытка
WIAImage = Новый COMОбъект("WIA.ImageFile");
WIAProcess = Новый COMОбъект("WIA.ImageProcess");
Исключение
ВызватьИсключение "Библиотека WIA недоступна на данном компьютере!";
КонецПопытки;
// Загружаем картинку из файла
WIAImage.LoadFile(ПутьКИсходномуФайлу);
// Настраиваем фильтр масштабирования
WIAProcess.Filters.Add(WIAProcess.FilterInfos("Scale").FilterID);
WIAProcess.Filters(1).Properties("MaximumWidth").Value = 800;
WIAProcess.Filters(1).Properties("MaximumHeight").Value = 600;
WIAProcess.Filters(1).Properties("KeepAspectRatio").Value = Истина;
// Применяем фильтр и сохраняем результат
СжатоеИзображение = WIAProcess.Apply(WIAImage);
СжатоеИзображение.SaveFile(ПутьКНовомуФайлу);
Этот способ надежен, работает «из коробки» на большинстве серверов под управлением ОС Windows и не требует установки платного программного обеспечения. Однако у него есть существенный недостаток — он не кроссплатформенный и не будет работать на серверах под управлением Linux.
В случаях, когда в базе данных уже накоплен огромный массив перетяжеленных картинок, обрабатывать их поочередно программным кодом внутри 1С может быть слишком долго и ресурсозатратно для сервера приложений. В такой ситуации эффективнее прибегнуть к пакетной обработке.
Для реализации этого подхода рекомендуем следующий алгоритм действий:
Развивая тему оптимизации графики, важно упомянуть, что в новых релизах платформы (начиная с 8.3.22) реализована полноценная поддержка формата WebP. Этот формат разработан Google специально для эффективного сжатия изображений без видимой потери качества.
Картинка в формате WebP весит в среднем на 30-40% меньше аналогичного файла в формате JPEG при идентичном визуальном качестве. Если вы проектируете систему с нуля или имеете возможность обновить платформу, рассмотрите перевод всех загружаемых картинок номенклатуры именно в формат WebP с помощью метода Обработка.УстановитьФормат(ФорматКартинки.WEBP).
Для иконок, логотипов и простых схематичных изображений идеальным выбором будет векторный формат SVG, нативная поддержка которого также реализована в последних релизах платформы. Векторные файлы имеют ничтожно малый вес и идеально масштабируются на любых мониторах с высоким разрешением (4K и выше) без размытия.