С развитием возможностей мобильных устройств и цифровых камер проблема хранения изображений в информационных базах 1С стала особенно острой. Фотографии в формате JPG часто имеют размер от 2 до 8 Мб и разрешение, значительно превышающее потребности бизнес-приложений. Начиная с версии платформы 8.3.14, разработчикам стал доступен мощный встроенный инструмент — объект ОбрабатываемаяКартинка. Он позволяет манипулировать изображениями без использования внешних компонент или вызовов сторонних библиотек. В этой статье мы подробно разберем, как оптимизировать размер картинок для экономии места в базе и ускорения передачи данных.
Прежде чем перейти к программному коду, проанализируем основные причины, по которым хранение оригинальных фото может быть неэффективным:
Рассмотрим сложный, но эффективный алгоритм, предложенный для случаев, когда нам критически важно, чтобы файл не превышал определенный порог (например, 300 Кб). Этот метод основан на цикличном уменьшении размеров изображения до тех пор, пока его вес в байтах не станет приемлемым.
Проанализируем функцию ПолучитьУжатуюКартинку:
Функция ПолучитьУжатуюКартинку(Крт, УжатьДо) Экспорт
Отступ = 0.9;
Крт_ = Крт;
// Цикл выполняется, пока текущий размер файла больше требуемого
Пока Крт_.РазмерФайла > УжатьДо Цикл
УжатьДо90 = Окр(УжатьДо * Отступ, 0);
КртШирина = Крт.Ширина;
КртВысота = Крт.Высота;
РзмКрт = Крт.РазмерФайла;
// Расчет коэффициента масштабирования на основе логарифмической зависимости
Кф = УжатьДо / РзмКрт;
Кф1 = Log(1.5 + Кф * Кф * 1.25);
Кф0 = Кф1 / 4;
Кф2 = 3 * (1 + Кф1) / 4;
Кф = Кф1;
НоваяШирина = Окр(КртШирина * Кф, 0);
НоваяВысота = Окр(КртВысота * Кф, 0);
// Использование объекта ОбрабатываемаяКартинка для изменения геометрии
ОбрКрт = Новый ОбрабатываемаяКартинка(Крт, Истина);
ОбрКрт.УстановитьРазмер(НоваяШирина, НоваяВысота);
Крт_ = ОбрКрт.ПолучитьКартинку();
// Вложенный цикл для уточнения коэффициента сжатия (метод деления пополам)
Пока ((Крт_.РазмерФайла > УжатьДо) ИЛИ (Крт_.РазмерФайла < УжатьДо90))
И (Кф2 - Кф0 > 0.025) Цикл
Если Крт_.РазмерФайла > УжатьДо Тогда
Кф2 = Кф1;
Кф = (Кф1 + Кф0) / 2;
Кф1 = Кф;
Иначе
Кф0 = Кф1;
Кф = (Кф2 + Кф1) / 2;
Кф1 = Кф;
КонецЕсли;
ОбрКрт = Новый ОбрабатываемаяКартинка(Крт, Истина);
НоваяШирина = Окр(КртШирина * Кф, 0);
НоваяВысота = Окр(КртВысота * Кф, 0);
ОбрКрт.УстановитьРазмер(НоваяШирина, НоваяВысота);
Крт_ = ОбрКрт.ПолучитьКартинку();
КонецЦикла;
Отступ = Отступ - 0.1;
Если Отступ < 0.6 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Крт_;
КонецФункции
В данном примере мы используем объект ОбрабатываемаяКартинка, инициализируя его исходным объектом типа Картинка. Параметр Истина в конструкторе указывает на то, что мы хотим работать с копией изображения. Метод УстановитьРазмер пропорционально (или принудительно) меняет количество пикселей, что напрямую влияет на итоговый объем занимаемой памяти.
В большинстве бизнес-сценариев (например, для прайс-листов или карточек товаров) достаточно просто ограничить максимальный размер картинки (например, не более 1000 пикселей по ширине). Это гораздо быстрее, так как не требует выполнения тяжелых операций в цикле. Выясним, как это реализовано в типовых конфигурациях, таких как УТ 11.5.
Функция ПреобразоватьФото(ИсходнаяКартинка, МаксимальнаяСторона = 800)
ИсходнаяШирина = ИсходнаяКартинка.Ширина;
ИсходнаяВысота = ИсходнаяКартинка.Высота;
// Если картинка и так маленькая, возвращаем оригинал
Если ИсходнаяШирина <= МаксимальнаяСторона И ИсходнаяВысота <= МаксимальнаяСторона Тогда
Возврат ИсходнаяКартинка;
КонецЕсли;
СоотношениеСторон = ИсходнаяШирина / ИсходнаяВысота;
Если ИсходнаяШирина > ИсходнаяВысота Тогда
НоваяШирина = МаксимальнаяСторона;
НоваяВысота = МаксимальнаяСторона / СоотношениеСторон;
Иначе
НоваяВысота = МаксимальнаяСторона;
НоваяШирина = МаксимальнаяСторона * СоотношениеСторон;
КонецЕсли;
ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
ОбрабатываемаяКартинка.УстановитьФормат(ФорматКартинки.JPEG);
ОбрабатываемаяКартинка.УстановитьРазмер(НоваяШирина, НоваяВысота);
Возврат ОбрабатываемаяКартинка.ПолучитьКартинку();
КонецФункции
Этот способ является более предсказуемым с точки зрения нагрузки на сервер. Мы один раз вычисляем новые размеры, сохраняя пропорции, и один раз вызываем метод ПолучитьКартинку. Обратите внимание на использование ФорматКартинки.JPEG — это гарантирует, что даже если исходный файл был в формате BMP или PNG, результат будет сохранен в сжатом виде.
При использовании данных методов следует учитывать несколько технических аспектов, которые могут повлиять на результат:
ОбрабатываемаяКартинка из файла удаляются все метаданные (дата съемки, модель камеры, GPS-координаты). Внимание: также удаляется информация об ориентации. Если фото было сделано на телефон вертикально, после обработки оно может "перевернуться" на бок. Чтобы этого избежать, проверяйте свойство Ориентация у исходной картинки и при необходимости применяйте метод Повернуть.ОбрабатываемаяКартинка в 1С не имеет прямого свойства "Качество" (Quality) для JPEG, как в профессиональных редакторах. Степень сжатия регулируется платформой автоматически при выполнении метода УстановитьРазмер.ФильтрКартинки. С его помощью можно не только менять размер, но и, например, преобразовывать картинки в черно-белый формат (Grayscale), что для сканов документов позволяет снизить вес файла в несколько раз без потери информативности.Проанализируем ситуацию: каждое преобразование картинки на сервере потребляет оперативную память. Если вы решите обработать миллион картинок в одном цикле, сервер может "упасть" из-за нехватки ресурсов. Разберем, как делать правильно:
Таким образом, мы выяснили, что современные версии 1С предоставляют все необходимые инструменты для эффективной работы с графикой. Использование объекта ОбрабатываемаяКартинка позволяет существенно оптимизировать ресурсы системы и повысить комфорт работы пользователей.