Программное создание картинки

В статье приводится алгоритм программного создания однотонной картинки на основе переданного цвета.

Как-то мне понадобилось сделать однотонные цветные закладки, чтобы пользователь мог сам выбирать цвет. Стандартный функционал 1С страниц панели, поддерживает только присвоение объекта типа Картинка для закладок. Возможно, есть решение в объектах ActiveX, но моя душа к такому способу не лежала. Но как говорится, если гора идет к Магомету, то Магомет идет к горе. Поэтому решил создать объект типа Картинка программно.

Для этого идеально подошел формат BMP (как самый простейший из форматов хранения изображений). Чтобы не заморачиваться с палитрой, выбрал 24-битную глубину изображения (байты цвета каждого пикселя хранятся в порядке Blue,Green,Red). Затем, не мудрствуя лукаво, создал однотонную картинку 16×16 в паинте и вооружившись HEX-редактором перенес оттуда заполненные поля заголовка файла в код 1С, который заполняет массив данных. Чтобы записать массив в бинарный файл, запихиваем его в COMSafeArray, который уже с помощью потока COMОбъекта «ADODB.Stream» сохраняем в файл.

Таким образом, путем нехитрых манипуляций родилась небольшая функция:

Функция СоздатьКартинку(Цвет)

    Данные = Новый Массив(822);

    // Заполняем заголовок файла служебной информацией

    Данные[0] = 66; Данные[1] = 77;
    Данные[2] = 54; Данные[3] = 03;
    Данные[10] = 54; Данные[14] = 40;
    Данные[18] = 16; Данные[22] = 16;
    Данные[26] = 01; Данные[28] = 24;
    Данные[38] = 195; Данные[39] = 14;
    Данные[42] = 195; Данные[43] = 14;

    // Заполняем всю картинку выбранным цветом
    // Единственный косяк в том, что нельзя выбрать ни WebЦвета, ни Windows
    // Как вариант, можно выбрать цвет на вкладке WevЦвета или Windows, затем перейдя на вкладку «из стиля»
    // поменять значение любого компонента цвета (красный, зеленый, синий) и вернуть его обратно
    Для Счетчик = 0 По 255 Цикл
        Данные[54 + Счетчик * 3] = Цвет.Синий;
        Данные[54 + Счетчик * 3 + 1] = Цвет.Зеленый;
        Данные[54 + Счетчик * 3 + 2] = Цвет.Красный;
    КонецЦикла;

    // Обводим рамочкой и не забываем, что строки в bmp-файле хранятся снизу-вверх
    Для Счетчик = 0 По 15 Цикл
        // рамка снизу
        Данные[54 + Счетчик * 3] = 0; Данные[55 + Счетчик * 3] = 0; Данные[56 + Счетчик * 3] = 0;
        // рамка сверху
        Данные[773 + Счетчик * 3] = 0; Данные[774 + Счетчик * 3] = 0; Данные[775 + Счетчик * 3] = 0;
        // рамка слева
        Данные[54 + Счетчик * 48] = 0; Данные[55 + Счетчик * 48] = 0; Данные[56 + Счетчик * 48] = 0;
        // рамка справа
        Данные[ 99 + Счетчик * 48] = 0; Данные[100 + Счетчик * 48] = 0; Данные[101 + Счетчик * 48] = 0;
    КонецЦикла;

    // Создаем bmp-файл
    ИмяФайла = ПолучитьИмяВременногоФайла(«bmp»);
    Поток = Новый COMОбъект(«ADODB.Stream»);
    Поток.Type = 1;
    Поток.Mode = 3;
    Поток.Open();
    Поток.Write(Новый COMSafeArray(Данные, «VT_UI1», Данные.Количество()));
    Поток.SaveToFile(ИмяФайла);
    Поток.Close();

    Возврат Новый Картинка(Новый ДвоичныеДанные(ИмяФайла));

КонецФункции

 Вот и все. Только пришлось добавить рамочку вокруг рисунка для красоты 🙂

9 Comments

  1. Serj1C

    очень интересно. я делал обработку для создания не только монотонных рисунков http://infostart.ru/public/77713/

    проще было бы, конечно, использовать ком объект потока, но хотелось все чисто внутренними методами 1С

    а так, беру на заметку

    Reply
  2. [AdepT]

    Там же целый минипаинт 🙂 А тут маленькая функция для создания иконки. Но, как говорится, на вкус и цвет… 🙂

    Reply
  3. CaSH_2004

    Хорошая и полезная тема с отличными комментариями. Как-то недавно пришлось столкнуться как можно из библиотеки картинок извлечь таким-же макаром отдельные картинки — перепахал весь код и ускорил в 10 раз, хотя помучаться прищлось, необычные методики для 1С. Вот все никак на статью не разрожусь.

    Reply
  4. dragonbridge

    C COMSafeArray неплохо придумал, надо будет взять на вооружение.

    Reply
  5. softservice14

    Как раз, то что нужно!

    Reply
  6. Anthon
    Reply
  7. Anthon

    не проверял на 1С-цвета ) поставил заглушку, если пользователь выберет цвет из 1Совских через ДиалогВыбораЦвета.

    Функция ПолучитьRGB(Цвет) Экспорт

    Попытка

    фд = Новый ФорматированныйДокумент;

    тфд = фд.Добавить(«Текст», Тип(«ТекстФорматированногоДокумента»));

    тфд.ЦветТекста = Цвет;

    Если (Цвет.Вид <> ВидЦвета.Абсолютный) И (Цвет.Вид <> ВидЦвета.WebЦвет) Тогда

    тфд.ЦветТекста = WebЦвета.Белый;//неизвестные цвета пусть будут белыми

    КонецЕсли;

    тмл = «»;

    фд.ПолучитьHTML(хтмл, Новый Структура);

    Исключение

    Сообщить(«Ошибка при построении служебного форматированного документа: » + ОписаниеОшибки(), СтатусСообщения.Важное);

    КонецПопытки;

    Попытка

    рЧтение = Новый ЧтениеHTML;

    рЧтение.УстановитьСтроку(хтмл);

    пострДом = Новый ПостроительDOM;

    докДом = пострДом.Прочитать(рЧтение);

    знчАтрибута = докДом.Тело.ДочерниеУзлы[1].ПервыйДочерний.Атрибуты[0].Значение;

    рЦвет16ричный = СокрЛП(СтрЗаменить(СтрЗаменить(знчАтрибута, «color: «, «»), «;», «»));

    Исключение

    Сообщить(«Ошибка при распознании содержания форматированного документа: » + ОписаниеОшибки(), СтатусСообщения.Важное);

    КонецПопытки;

    Возврат ПолучитьRGBИз16(рЦвет16ричный);

    КонецФункции

    Reply
  8. shmalevoz
    Reply
  9. shmalevoz
    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *