Программное формирование картинки в 1С:Предприятие 8.3.9 (ПотокВПамяти / ЗаписьДанных)

Публикация № 1061803

Разработка - Универсальные функции

картинка bmp программно

В статье представлен код программного формирования картинки (двоичные данные) без всяких внешних компонент, без формирования строки Base64, используя лишь встроенные механизмы 1С предприятие 8.3.9 (объекты ПотокВПамяти и ЗаписьДанных). Сам по себе код формирования картинки не несёт ничего нового. Всё описано в википедии. Захотелось попробовать новые методы, но никак не доходитили руки. В приложении обработка практически с этим же кодом.

Приступим к делу.

Будем формировать картинку в два этапа:
1. Сначала подготовим данные картинки, т.н. RGB матрицу. Именно здесь мы рисуем нашу будущую картинку путём определения цвета каждого пикселя. Т.е., если нужно нарисовать что-то своё, то меняем код именно здесь. 
2. А потом по этим данным уже сформируем двоичные данные.
Листинг функций представлен ниже. Плюс небольшие замечания.

Обработка создавалась любопытства ради. Применение каждый может определить для себя сам.

Итак, к делу:

Сначала вспомогательная функция формирования матрицы цветов пикселей. Собственно здесь мы описываем цвет каждого пикселя по его координатам.
Создаём двумерный массив высотой и шириной в пикселях с нашу картинку. Элементы массива - структура с RGB компонентами цвета. Не самый лучший вариант в плане производительности, но самый наглядный из тех, что я смог придумать.

&НаСервереБезКонтекста
Функция МатрицаЦветовRGB(Высота, Ширина)
	
	// Устанавливаем размеры матрицы по которой сформируется картинка
	ТекМатрицаЦветовRGB = Новый Массив(Высота, Ширина);
	
	Для Индекс1 = 1 По Высота Цикл
		Для Индекс2 = 1 По Ширина Цикл
			
			// Далее идёт установка цвета пикселя в зависимости от координат.
			// Именно этот код предполагается модифицировать
			#Область Определение_цвета_пикселя

			Если ((Cos(Индекс2/Ширина*5*3.14)/2+0.5)*0.6 + 0.4)*Высота > Индекс1 Тогда
				ТекКрасный 	= Цел(255*Индекс1/Высота);
				ТекЗеленый 	= 50;
				ТекСиний 	= 50;
			Иначе
				ТекКрасный = 255;
				ТекЗеленый = 255; 
				ТекСиний = 255; 
			КонецЕсли;			
					
			#КонецОбласти
			
			ТекМатрицаЦветовRGB[Индекс1-1][Индекс2-1] = Новый Цвет(ТекКрасный, ТекЗеленый, ТекСиний);
			
		КонецЦикла;
	КонецЦикла;	
	
	Возврат ТекМатрицаЦветовRGB
	
КонецФункции

По матрице формируем двоичные данные картинки. Большую часть кода занимает формирование шапки файла. Описание значений можно найти на википедии. Хотя там и написано довольно понятно, однако на создание рабочего кода у меня ушло несколько часов.

&НаСервереБезКонтекста
Функция СоздатьКартинку(МатрицаЦветовRGB)
	
	Высота = МатрицаЦветовRGB.Количество();
	Ширина = МатрицаЦветовRGB[0].Количество();
	
	// Для простоты формирования возьемём 24 бита. По 8 бит на каждый канал. Альфаканал не используем. 
	ТекГлубинаЦвета = 3; // Измеряется в байтах. 	
	
	// Каждая строка должна содержать количество байтов кратное 4.
	БайтовДополнение = (4-ТекГлубинаЦвета*Ширина%4)%4; 
	
	РазмерФайла = ТекГлубинаЦвета*Ширина*Высота + Высота*БайтовДополнение;	
	
	///////////////////////////////////////////////////////////////////////////////
		
	ПотокТело = Новый ПотокВПамяти();
	ЗаписьДанных = Новый ЗаписьДанных(ПотокТело);
		
	//BITMAPFILEHEADER
	
	//bfType 
	ЗаписьДанных.ЗаписатьЦелое16(16973, ПорядокБайтов.BigEndian); // 0x424D big-endian = 0x4D42 little-endian. Признак формата. Всегда это значение.
	//bfSize
	ЗаписьДанных.ЗаписатьЦелое32(54 + РазмерФайла);
	//bfReserved1
	ЗаписьДанных.ЗаписатьЦелое16(0);	
	//bfReserved2
	ЗаписьДанных.ЗаписатьЦелое16(0);	
	//bfOffBits
	ЗаписьДанных.ЗаписатьЦелое32(54);
	
	//BITMAPINFOHEADER // версия 3
	// biSize
	ЗаписьДанных.ЗаписатьЦелое32(40); 
	// biWidth
	ЗаписьДанных.ЗаписатьЦелое32(Ширина);			// ширина изображения в пикселах 
	// biHeight
	ЗаписьДанных.ЗаписатьЦелое32(Высота);			// высота изображения в пикселах
	// biPlanes
	ЗаписьДанных.ЗаписатьЦелое16(1);				// содержит единицу
	// biBitCount
	ЗаписьДанных.ЗаписатьЦелое16(ТекГлубинаЦвета*8);	// количество бит на пиксел 
	// biCompression
	ЗаписьДанных.ЗаписатьЦелое32(0);				// тип сжатия 
	// biSizeImage
	ЗаписьДанных.ЗаписатьЦелое32(РазмерФайла);		// размер изображения в байтах
	// biXPelsPerMeter
	ЗаписьДанных.ЗаписатьЦелое32(0);				// горизонтальное разрешение в пикселах на метр 
	// biYPelsPerMeter
	ЗаписьДанных.ЗаписатьЦелое32(0); 				// вертикальное разрешение в пикселах на метр 
	// biClrUsed
	ЗаписьДанных.ЗаписатьЦелое32(0);				//  количество используемых цветовых индексов в палитре 
	// biClrImportant
	ЗаписьДанных.ЗаписатьЦелое32(0);				// количество индексов
	
	///////////////////////////////////////////////////////////////////////////////
		
	Для Выс = 1 По Высота Цикл	// строки снизу вверх		
			
		Для Шир = 1 По Ширина Цикл
			
			ЦветаПикселя = МатрицаЦветовRGB[Выс-1][Шир-1];
			ЗаписьДанных.ЗаписатьБайт(ЦветаПикселя.Синий);
			ЗаписьДанных.ЗаписатьБайт(ЦветаПикселя.Зеленый);
			ЗаписьДанных.ЗаписатьБайт(ЦветаПикселя.Красный);
						
		КонецЦикла;
		
		// Забиваем нулями остаток строки. Так как размер строки должен быть кратен 4 байтам.
		Для Доп = 1 По БайтовДополнение Цикл		
			ЗаписьДанных.ЗаписатьБайт(0); 
		КонецЦикла;
		
	КонецЦикла;
		
	ЗаписьДанных.Закрыть();
	
	ДвоичныеДанныеТело = ПотокТело.ЗакрытьИПолучитьДвоичныеДанные();
	
	Возврат ДвоичныеДанныеТело;
		
КонецФункции

 

Теперь вернёмся к вопросу об использовании. Почему-то в 1С у меня не хотели отображаться bmp-файлы. Даже, если я их создавал в паинте. Получилось обойти проблему с помощью встроенного метода Преобразовать, преобразовывая картинки в формат png:

ТекМатрицаЦветовRGB = МатрицаЦветовRGB(ВысотаКартинок, 200);
ТекКартинкаДвоичныеДанные = СоздатьКартинку(ТекМатрицаЦветовRGB);

ТекКартинка = Новый Картинка(ТекКартинкаДвоичныеДанные);
ТекКартинкаПНГ = ТекКартинка.Преобразовать(ФорматКартинки.PNG);

Здесь же на инфостарте был найден способ отображения картинок в табичной части / динамическом списке используя навигационные ссылки. Статью к сожалению, найти не могу. В кратце:
Создаём справочник КартинкиДляТаблицы с двумя реквизитами:
1. ДанныеКартинки - Тип: ХранилищеЗначения
2. АдресКартинки - Тип: Строка(0)

Формируем картинку, и записываем в элемент справочника:

 

// Создаём картинку
ТекКартинкаДвоичныеДанные = СоздатьКартинку(ТекМатрицаЦветовRGB);
ТекКартинка = Новый Картинка(ТекКартинкаДвоичныеДанные);

// Преобразуем в PNG
ТекКартинкаПНГ = ТекКартинка.Преобразовать(ФорматКартинки.PNG);	

// Создаём элемент справочника
НовЭлемент = Справочники.КартинкиДляТаблицы.СоздатьЭлемент();

// Прописываем наименование, если нужно
НовЭлемент.Наименование = "График1";

// Присваиваем данные картинки. Формат PNG уже сжат, поэтому тратить ресурсы на излишнее сжатие не будем.
НовЭлемент.ДанныеКартинки = Новый ХранилищеЗначения(ТекКартинкаПНГ, Новый СжатиеДанных(0));

// Записываем, так как для ПолучитьНавигационнуюСсылку нужна ссылка.
НовЭлемент.Записать();

// Получаем навигационную ссылку на реквзит "ДанныеКартинки" у данного элемента справочника
// и записываем полученное значение
НовЭлемент.АдресКартинки = ПолучитьНавигационнуюСсылку(НовЭлемент.Ссылка, "ДанныеКартинки");

// После чего сохраняем элемент справочника
НовЭлемент.Записать(); 

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

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	КартинкиДляТаблицы.Ссылка КАК Ссылка,
|	КартинкиДляТаблицы.АдресКартинки КАК АдресКартинки
|ИЗ
|	Справочник.КартинкиДляТаблицы КАК КартинкиДляТаблицы";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	НовСтрока = Таблица.Добавить();
	НовСтрока.Картинка = Выборка.АдресКартинки;
	НовСтрока.Справочник = Выборка.Ссылка;
КонецЦикла;

Вуаля:

 

В файлах:
1. обработка с этим кодом
2. выгрузка конфигурации с этим справочником картинок и обработкой.

Скачать файлы

Наименование Файл Версия Размер
Формирование картинки.epf

.epf 9,37Kb
17.05.19
5
.epf 9,37Kb 5 Скачать
СправочникДляКартинок_ФормированиеКартинок.cf

.cf 19,16Kb
17.05.19
4
.cf 19,16Kb 4 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо свернутое
1. Serj1C 479 17.05.19 11:39 Сейчас в теме
Круто!
Тоже с 2013 года хочу свою обработку адаптировать под новые возможности 8.3
https://infostart.ru/public/77713/

Как долго генерируется картинка?
3. Darklight 22 17.05.19 15:25 Сейчас в теме
Волны в примере бегут? Если нет динамики - то это не так интересно
4. Поручик 4428 17.05.19 15:35 Сейчас в теме
7. Жолтокнижниг 250 09.06.19 23:54 Сейчас в теме
Есть еще вариант формирования картинок - SVG, поддержка с 8.3.?

Увы 1с не умеет SVG анимацию.
Оставьте свое сообщение

См. также

Программное создание динамического списка на управляемой форме. (Динамическое создание динамического списка). Готовая процедура + обработка - демонстрационный пример Промо

Практика программирования Универсальные функции v8::УФ 1cv8.cf Абонемент ($m)

Если у вас возникает необходимость на форму влиять динамически и создавать элементы управляемой формы программно, а особенно хотите вывести программно (динамически) динамический список, вам будет интересна эта процедура. Процедура включает также возможность формирования своей командной панели (а-ля снятие галочки "Автозаполнение" у стандартной командной панели списка).

1 стартмани

19.01.2018    57075    rpgshnik    29    

Библиотека программного изменения формы (УФ)

Инструментарий разработчика Работа с интерфейсом Универсальные функции v8 1cv8.cf Абонемент ($m)

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

1 стартмани

07.08.2020    3774    BuriyLesha    17    

Сохранение настроек колонок

Практика программирования Работа с интерфейсом Универсальные функции v8 Абонемент ($m)

Сохранение настроек колонок табличных полей. Получение имени формы из модуля формы. Для обычных форм.

1 стартмани

10.07.2020    950    Arc    1    

Универсальные функции: разложение произвольной строки адреса в структуру

Практика программирования Универсальные функции v8 1cv8.cf Абонемент ($m)

Процедуры и функции раскладывают произвольную строку адрес в структуру по ключевым словам.

1 стартмани

30.12.2019    3556    vik070777    10    

Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов Промо

Практика программирования Математика и алгоритмы Универсальные функции Производительность и оптимизация (HighLoad) v8 1cv8.cf Россия Абонемент ($m)

Восстановление партий, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

26.05.2017    48868    DarkAn    86    

Полезные процедуры и функции для программиста

Практика программирования Универсальные функции v8 1cv8.cf Россия Абонемент ($m)

Все мы пишем программный код и часто используем процедуры, облегчающие его написание. Ниже приведена выборка таких полезных процедур и функций.

07.10.2019    29392    HostHost    40    

Работа с графической схемой в объектной модели DOM

Универсальные функции v8 v8::УФ Абонемент ($m)

Пример кода для работы с графической схемой в объектной модели DOM, платформа 8.3.12.

1 стартмани

04.06.2019    7937    botokash    19    

Корректировка движений документа

Универсальные функции v8 1cv8.cf Абонемент ($m)

Корректировка движений документа после его проведения по типовому алгоритму.

1 стартмани

26.05.2019    4513    rutadmeen    0    

Ускорение для Клиент-Банка Промо

Банковские операции Обмен с банком Универсальные функции Банковские операции v8 1cv8.cf Абонемент ($m)

У вас много платежей и клиент-банк долго их читает? Есть проверенная практикой идея, как это ускорить.

1 стартмани

08.10.2012    23718    Yashazz    15    

Альтернатива внешним печатным формам. ЗУП 3.1

Печатные формы документов Универсальные функции Зарплата Практика программирования Зарплата Разработка v8 v8::СПР ЗУП3.x Абонемент ($m)

Как в ЗУП 3.1.8 отказаться от внешних печатных форм и расширением увеличить количество полей, доступных при редактировании макетов, для изменения печатных форм Т1, Т5, Т8 и аналогичные пользователями.

1 стартмани

30.01.2019    14275    Mogilnikova    3    

Использование подсистемы БСП "Заполнение объектов"

Практика программирования Универсальные функции БСП (Библиотека стандартных подсистем) v8 v8::УФ 1cv8.cf Россия Абонемент ($m)

Применение механизмов БСП для добавления новых команд заполнения к формам различных объектов. Использование расширений конфигурации для доработки. Шаблоны для реализации собственных команд заполнения.

1 стартмани

23.11.2018    25363    ids79    23    

Доработка функции ОбщегоНазначения.ЗаменитьСсылки для автоматической чистки или свёртки табличных частей

Универсальные функции v8 Абонемент ($m)

Стандартная обработка по замене дублей ругается на документ с неуникальными строками. Предполагается, что их нужно либо а) удалить, либо б) свернуть. Я немного модифицировал код функции ОбщегоНазначения.ЗаменитьСсылки, встроив в него вызов процедуры, переопределяемой в модуле менеджера соответствующего документа. И в этом модуле менеджера мы уже сами определяем - удалить или свернуть. Ну и вообще там чего хошь можно с этой коллекцией сделать - сам же ж процедуру пишешь...

1 стартмани

12.09.2018    4092    albert.goncharov    0    

Сохранение реквизитов и табличных частей объектов в XML Промо

Обмен через XML Универсальные функции v8 1cv8.cf Абонемент ($m)

Пример того, как можно сохранять и загружать объекты 1С методами встроенных объектов ЗаписьXML и ЧтениеXML.

1 стартмани

25.11.2011    21710    saiten    21    

Пропорциональное распределение в запросе

Универсальные функции Практика программирования v8 1cv8.cf Абонемент ($m)

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

1 стартмани

28.06.2018    11841    invertex    7    

Заполнение справочника с изображениями элементами по умолчанию

Практика программирования Обмен через XML Универсальные функции v8 Абонемент ($m)

Пример одного из решений, как можно заполнить справочник с изображениями значениями по умолчанию включая сами изображения. Сами изображения взяты из программы MapSource 6.16.3. Данные для загрузки хранятся в макете в формате XML.

1 стартмани

26.03.2018    8624    Kim1C    0    

Проверка таблицы на дублирование строк (ТаблицаЗначений, ТабличнаяЧасть) и получение массива таких строк

Практика программирования Универсальные функции v8 1cv8.cf Абонемент ($m)

Функция для проверки дублирования строк в ТаблицеЗначений или ТабличнойЧасти. Также, если необходимо, возвращает массив задублированных строк (можно обработать).

1 стартмани

05.02.2018    11234    uri1978    27    

Работа с кодами - числами, датами, кодами справочников, номерами документов, идентификаторами в 1С и в других базах данных

Универсальные функции v8 1cv8.cf Россия Абонемент ($m)

Поддерживается преобразование Кодов на основе Алфавитов, в том числе ''блочных" кодов - состоящих из блоков (подстрок) одинаковой длины (например: 8, 16, 32-битные коды, Хэши и т.п.). Функции доступны на Клиенте и на Сервере. Демо-примеры сделаны на управляемых формах. Тестировалось на платформах серии 8.3.10.

1 стартмани

28.11.2017    7491    newold2    1    

Размеры управляемой формы

Практика программирования Работа с интерфейсом Универсальные функции v8 1cv8.cf Абонемент ($m)

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

1 стартмани

08.10.2017    26586    json    9    

Пример универсальной функции для создания схемы компоновки данных

Практика программирования Универсальные функции v8::СКД 1cv8.cf Россия Абонемент ($m)

Если вам приходится часто создавать схему компоновки данных программно или вы начинающий специалист и пытаетесь разобраться, что же за зверь такой СКД, то эта статья может оказаться вам полезной. Функция создает схему компоновки с минимально необходимой структурой данных. С помощью передачи дополнительных параметров есть возможность добавления ресурсов и оформления.

1 стартмани

12.01.2017    31898    dbachinsky    32    

Функция преобразования промежутка времени в строку

Универсальные функции v8 1cv8.cf Россия Абонемент ($m)

Функция предназначена для преобразования промежутка времени в строку с разбивкой по годам, дням, часам, минутам, секундам.

1 стартмани

23.09.2016    10072    vovant    1    

1С 8.2 переключение раскладки клавиатуры (с помощью dynwrap.dll)

Разработка внешних компонент Универсальные функции v8 Абонемент ($m)

Функция для автоматического переключения раскладки клавиатуры. (с помощью dynwrap.dll) Дабы не переключать каждый раз (при вводе информации в разных полях) с "Rus" на "Eng", можно эту работу возложить на функцию.

1 стартмани

22.05.2013    15164    Serg23ru    24    

Конвертер Даты из числового формата Excel

Загрузка и выгрузка в Excel Универсальные функции v8 1cv8.cf Абонемент ($m)

Столкнувшись с проблемой загрузки в 1С из Excel Даты-Времени в числовом формате к удивлению не нашел нигде подобных формул. Может потому что они уж слишком банальны, а может потому что они "тайное знание посвященных". В общем, эта обработка пример конвертации Excel <=> 1C

1 стартмани

17.04.2013    18301    vova196    5    

Точка Актуальности для 1С 8

Практика программирования Универсальные функции v8 УТ10 Абонемент ($m)

Все знают, что такое ТА для 1с 7.7 И этот механизм отсутствует в 1С 8. Но многие бухгалтера привыкли к нему. Почему бы тогда его не реализовать?

1 стартмани

18.12.2012    20521    Sykoku    28    

Ограничение на проведение реализаций по группе доступности складов в УТ 10.3

Практика программирования Универсальные функции Учет ТМЦ Учет ТМЦ v8 УТ10 Абонемент ($m)

В стандартной конфигурации УТ 10.3, настройка "группы доступности складов" не накладывает ограничения на продажи с определённых складов. Группа доступности складов позволяет наложить ограничение лишь на автоматическое размещение товаров в заказе покупателей, т.е. менеджер может вручную выбрать размещение и совершить продажу. Данная доработка исправляет эту ситуацию.

12.04.2012    12172    pusix    8    

Синхронизация с сервером 1С во внешнем соединении

Внешние источники данных Универсальные функции v8 1cv8.cf Абонемент ($m)

Позволяет установить время удаленного SQL-сервера на компьютере при выполнении обмена через Внешнее соединение

1 стартмани

27.09.2011    13363    sml    6    

Как превратить линейно-периодический отчёт в многолинейно-периодический (в платформах 8.х)

Универсальные функции Анализ учета v8 1cv8.cf Абонемент ($m)

Навеяно http://infostart.ru/public/90001/ - решение на основе пользовательских полей в СКД

1 стартмани

27.09.2011    17094    e.kogan    35