Как исправить ошибку «Недостаточно памяти» при определении формата картинки в 1С?

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

При работе с изображениями в 1С:Предприятие 8.3, особенно в старых типовых конфигурациях вроде Управление торговлей 10.3, разработчики часто сталкиваются со специфической проблемой. При попытке программно определить формат изображения с помощью метода Картинка.Формат() или просто при просмотре карточки номенклатуры система выдает критическую ошибку «Недостаточно памяти», после чего работа программы аварийно завершается. Самое неприятное в этой ситуации то, что стандартная конструкция Попытка...Исключение не спасает — 1С «вылетает» до того, как код перейдет в блок обработки ошибки.

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

Выясняем причину возникновения ошибки

Проанализируем ситуацию: файл изображения может иметь вполне стандартный размер (например, 200 Кб) и успешно открываться обычными средствами Windows (Paint, Просмотр фотографий). Однако встроенный в 1С механизм работы с графикой, использующий системные библиотеки GDI+, при анализе заголовка файла натыкается на структуру, которую не может корректно интерпретировать.

Основными техническими причинами являются:

  1. Прогрессивный JPEG (Progressive JPEG): Такие файлы записываются слоями. Если алгоритм декодирования в конкретной версии платформы 1С не справляется с чтением заголовка такого слоя, он может зациклиться или запросить некорректный объем оперативной памяти.
  2. Цветовая модель CMYK: Изображения, подготовленные для полиграфии, часто содержат четыре цветовых канала вместо трех (RGB). 1С плохо работает с такими файлами в методе Формат().
  3. Избыточные метаданные (EXIF/XMP): Некоторые графические редакторы записывают в заголовок файла огромные блоки служебной информации. При попытке 1С прочитать формат, она пытается распарсить весь заголовок, что приводит к переполнению буфера.
  4. Нулевое разрешение: Если в свойствах картинки прописано 0 DPI, это может вызвать фатальную ошибку при расчете геометрических параметров объекта Картинка.

Шаг 1: Локализация проблемных изображений

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

Рассмотрим пример кода для поиска проблемных объектов:


Процедура ПоискБитныхКартинок()
    Выборка = Справочники.ХранилищеДополнительнойИнформации.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Записываем ID в лог перед началом обработки
        ЗаписатьВЛог("Проверка объекта: " + Выборка.Ссылка + " (" + Выборка.Наименование + ")");
        
        Попытка
            КартинкаОбъект = Выборка.Хранилище.Получить();
            Если ТипЗнч(КартинкаОбъект) = Тип("Картинка") Тогда
                // Именно здесь происходит падение
                ТипФайла = КартинкаОбъект.Формат(); 
            КонецЕсли;
        Исключение
            // Сюда код может не дойти при жестком падении
            ЗаписатьВЛог("Обнаружена ошибка (обработано): " + Выборка.Ссылка);
        КонецПопытки;
        
        ЗаписатьВЛог("Успешно завершено");
    КонецЦикла;
КонецПроцедуры

Процедура ЗаписатьВЛог(ТекстСообщения)
    Текст = Новый ЗаписьТекста("C:\temp\check_images.log", КодировкаТекста.UTF8, , Истина);
    Текст.ЗаписатьСтроку("" + ТекущаяДата() + ": " + ТекстСообщения);
    Текст.Закрыть();
КонецПроцедуры

При запуске этой процедуры 1С рано или поздно закроется. Вам нужно будет открыть файл check_images.log. Последний объект, для которого не появилась запись «Успешно завершено», и является причиной сбоя. Запишите его идентификатор, перезапустите 1С и запустите проверку заново, начиная со следующего по порядку объекта.

Шаг 2: Исправление изображений (Нормализация)

Как показывает практика и обсуждения на форумах, самым простым и эффективным способом «лечения» такой картинки является её пересохранение. Если открыть проблемный файл в стандартном редакторе Paint и нажать «Сохранить», редактор перепишет заголовки файла в стандартный формат (Baseline JPEG), вычистит некорректные метаданные и установит верную цветовую модель.

Порядок действий:

  1. Выгрузите картинку из 1С на диск (метод Картинка.Записать() обычно работает без ошибок, так как он просто копирует двоичные данные).
  2. Откройте файл в графическом редакторе.
  3. Сохраните его.
  4. Загрузите обратно в справочник 1С.

После этой процедуры метод Картинка.Формат() начнет работать корректно.

Шаг 3: Безопасный способ определения формата (через двоичные данные)

Если вы хотите полностью обезопасить свой код от падений платформы, мы рекомендуем отказаться от использования метода Картинка.Формат() в пользу анализа сигнатур файлов. Каждый формат файла (JPEG, PNG, GIF) имеет уникальную последовательность байтов в самом начале. Чтение двоичных данных не задействует графический движок 1С и не вызывает ошибок памяти.

Разберем, как реализовать безопасную функцию определения формата:


Функция ОпределитьФорматБезопасно(Картинка)
    ДвоичныеДанные = Картинка.ПолучитьДвоичныеДанные();
    Чтение = Новый ЧтениеДанных(ДвоичныеДанные);
    ПервыеБайты = Чтение.Прочитать(4).РазложитьПоБайтам();
    
    // JPEG начинается с FF D8 FF
    Если ПервыеБайты[0] = 255 И ПервыеБайты[1] = 216 И ПервыеБайты[2] = 255 Тогда
        Возврат ФорматКартинки.JPEG;
    // PNG начинается с 89 50 4E 47 (в десятичном виде: 137 80 78 71)
    ИначеЕсли ПервыеБайты[0] = 137 И ПервыеБайты[1] = 80 И ПервыеБайты[2] = 78 Тогда
        Возврат ФорматКартинки.PNG;
    // GIF начинается с 47 49 46 38 (в десятичном виде: 71 73 70 56)
    ИначеЕсли ПервыеБайты[0] = 71 И ПервыеБайты[1] = 73 И ПервыеБайты[2] = 70 Тогда
        Возврат ФорматКартинки.GIF;
    КонецЕсли;
    
    Возврат ФорматКартинки.НеизвестныйФормат;
КонецФункции

Использование такого подхода гарантирует, что ваша обработка выгрузки на сайт (например, в Битрикс) не прервется из-за одной некорректной картинки.

Дополнительные рекомендации

Проанализируем еще несколько вариантов решения проблемы, если обновление платформы до последних версий (где многие ошибки работы с GDI+ исправлены) невозможно:

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

← На главную