Как программно сжать или изменить размер изображения в 1С:Предприятие 8.3.14 и выше

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

С развитием возможностей мобильных устройств и цифровых камер проблема хранения изображений в информационных базах 1С стала особенно острой. Фотографии в формате JPG часто имеют размер от 2 до 8 Мб и разрешение, значительно превышающее потребности бизнес-приложений. Начиная с версии платформы 8.3.14, разработчикам стал доступен мощный встроенный инструмент — объект ОбрабатываемаяКартинка. Он позволяет манипулировать изображениями без использования внешних компонент или вызовов сторонних библиотек. В этой статье мы подробно разберем, как оптимизировать размер картинок для экономии места в базе и ускорения передачи данных.

Зачем нужно сжимать картинки в 1С?

Прежде чем перейти к программному коду, проанализируем основные причины, по которым хранение оригинальных фото может быть неэффективным:

  1. Размер информационной базы: Сотни тысяч полноразмерных фотографий могут превратить базу объемом в несколько гигабайт в хранилище на сотни терабайт, что усложняет резервное копирование и обслуживание SQL-сервера.
  2. Производительность: Загрузка картинки весом 5 Мб в форму документа на слабом интернет-канале занимает значительное время, что раздражает пользователей.
  3. Обмен данными: При выгрузке товаров на сайт или в мобильное приложение передача "тяжелых" файлов создает избыточную нагрузку на сеть.
  4. Особенности экспорта: В современных версиях платформы (например, в режиме совместимости 8.3.25) при сохранении табличных документов в Excel картинки могут внедряться в исходном разрешении, даже если визуально они уменьшены. Это приводит к созданию огромных файлов Excel.

Метод 1: Итерационное сжатие до целевого веса в байтах

Рассмотрим сложный, но эффективный алгоритм, предложенный для случаев, когда нам критически важно, чтобы файл не превышал определенный порог (например, 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 Тогда
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Крт_;
КонецФункции

В данном примере мы используем объект ОбрабатываемаяКартинка, инициализируя его исходным объектом типа Картинка. Параметр Истина в конструкторе указывает на то, что мы хотим работать с копией изображения. Метод УстановитьРазмер пропорционально (или принудительно) меняет количество пикселей, что напрямую влияет на итоговый объем занимаемой памяти.

Метод 2: Пропорциональное изменение размера по максимальной стороне

В большинстве бизнес-сценариев (например, для прайс-листов или карточек товаров) достаточно просто ограничить максимальный размер картинки (например, не более 1000 пикселей по ширине). Это гораздо быстрее, так как не требует выполнения тяжелых операций в цикле. Выясним, как это реализовано в типовых конфигурациях, таких как УТ 11.5.


Функция ПреобразоватьФото(ИсходнаяКартинка, МаксимальнаяСторона = 800)
    ИсходнаяШирина = ИсходнаяКартинка.Ширина;
    ИсходнаяВысота = ИсходнаяКартинка.Высота;
    
    // Если картинка и так маленькая, возвращаем оригинал
    Если ИсходнаяШирина <= МаксимальнаяСторона И ИсходнаяВысота <= МаксимальнаяСторона Тогда
        Возврат ИсходнаяКартинка;
    КонецЕсли;
    
    СоотношениеСторон = ИсходнаяШирина / ИсходнаяВысота;
    
    Если ИсходнаяШирина > ИсходнаяВысота Тогда
        НоваяШирина = МаксимальнаяСторона;
        НоваяВысота = МаксимальнаяСторона / СоотношениеСторон;
    Иначе
        НоваяВысота = МаксимальнаяСторона;
        НоваяШирина = МаксимальнаяСторона * СоотношениеСторон;
    КонецЕсли;
    
    ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
    ОбрабатываемаяКартинка.УстановитьФормат(ФорматКартинки.JPEG);
    ОбрабатываемаяКартинка.УстановитьРазмер(НоваяШирина, НоваяВысота);
    
    Возврат ОбрабатываемаяКартинка.ПолучитьКартинку();
КонецФункции

Этот способ является более предсказуемым с точки зрения нагрузки на сервер. Мы один раз вычисляем новые размеры, сохраняя пропорции, и один раз вызываем метод ПолучитьКартинку. Обратите внимание на использование ФорматКартинки.JPEG — это гарантирует, что даже если исходный файл был в формате BMP или PNG, результат будет сохранен в сжатом виде.

Важные нюансы работы с ОбрабатываемаяКартинка

При использовании данных методов следует учитывать несколько технических аспектов, которые могут повлиять на результат:

Рекомендации по оптимизации производительности

Проанализируем ситуацию: каждое преобразование картинки на сервере потребляет оперативную память. Если вы решите обработать миллион картинок в одном цикле, сервер может "упасть" из-за нехватки ресурсов. Разберем, как делать правильно:

  1. Выполняйте сжатие в момент загрузки файла в систему. Не храните оригиналы, если они вам не нужны.
  2. Если требуется пакетная обработка уже накопленных данных, используйте фоновые задания с небольшими порциями (по 50-100 картинок за транзакцию).
  3. Для высоконагруженных систем рассмотрите возможность выноса хранения файлов из SQL-базы во внешние тома хранения (настройки в стандартных библиотеках БСП позволяют сделать это прозрачно для пользователя).

Таким образом, мы выяснили, что современные версии 1С предоставляют все необходимые инструменты для эффективной работы с графикой. Использование объекта ОбрабатываемаяКартинка позволяет существенно оптимизировать ресурсы системы и повысить комфорт работы пользователей.

← На главную