Читаем *.bmp напрямую в ТабДок двоичными данными

12.04.17

Интеграция - Файловый обмен (TXT, XML, DBF), FTP

После полученного интереса к публикации http://infostart.ru/public/601635/ о одном из способов формирования изображений в 1С я решил продолжить изучать другие возможности "рисования" в 1С. Естественно, самым простым форматом после svg будет старый добрый растр в bmp. Но когда приступил к написанию - понял, что формировать картинку с "0", наверное, будет нечестно по отношению к читателю, и для начала нужно разобрать, что такое bmp как формат, как его читать и, главное, показать примеры работы с новыми механизмами платформы.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование SM По подписке [?] Купить один файл
Обработка чтения bmp в ТабДок
.epf 9,02Kb
11
11
1 SM
Скачать Купить за 1 850 руб.

Обработка, прикрепленная к статье, опять написана в стол и не имеет практического применения, но имея ее, конфигуратор и клавишу F10, думаю, понять, как там все устроено в bmp, гораздо легче. Потому помимо выкладок кода прикреплю и ее, хотя слепить такую же, скопировав код ниже - не составит проблем.

Так вот, поняв, что сначала надо разобраться с самим форматом, научиться его читать, я, естественно, подумал о "повороте" изображения. Но, вспомнив про встроенные методы платформы, которые позволяют делать это проще и быстрее, решил, что это не интересно.

Неинтересный поворот картинки:

Картинка = Новый Картинка("C:\My Documents\My Pictures\home.bmp");
ОбработчикКартинок = Новый ОбработкаКартинок;

Картинка_90 = ОбработчикКартинок.Повернуть(Картинка, 90);

Вопросы преобразования в 1С тоже более или менее решены:

Картинка.Преобразовать(ФорматКартинки.PNG);

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

Описание формата bmp подробно расписано на вики: https://ru.wikipedia.org/wiki/BMP мы будем читать, полагая, что на вход нам подали файл версии №3. Декодер на все возможные версии занял бы много кода, да и не имеет практического смысла. Исходя из описания формата получилась следующая процедура чтения:

&НаКлиенте
Функция ДекодироватьИВывести(ПутьКФайлу)
		
	ПотокИсходный          = ФайловыеПотоки.ОткрытьДляЧтения(ПутьКФайлу);
	ЧтениеДанных           = Новый ЧтениеДанных(ПотокИсходный);
	//читаем 14 байт соответствующих структуре описания файла
	Буфер_BITMAPFILEHEADER		   = ЧтениеДанных.ПрочитатьВБуферДвоичныхДанных(14);
	//для bitmap допустима сигнатура 424D или 4D42
	Сигнатура 			   = Буфер_BITMAPFILEHEADER.ПрочитатьЦелое16(0);
	
	Если Сигнатура <> 19778 И Сигнатура <> 16973 Тогда
		Возврат "Выбранный файл не является файлом формата bitmap";
	КонецЕсли;
	
	РазмерФайлБайт = Буфер_BITMAPFILEHEADER.ПрочитатьЦелое32(2);
	ПоложениеМассиваПикселей = Буфер_BITMAPFILEHEADER.ПрочитатьЦелое32(10);
	
	//т.к. читаем не все сразу (в образовательных целях)следующей итерацией просто считаем 
	//один байт, это будет адрес 0E. в нем содержится информация 
	//о размере следующей структуры - BITMAPINFO
	
	Длина_BITMAPINFO = ЧтениеДанных.ПрочитатьЦелое32();
	
	//пока мы работаем только с 3й версией файла, 
	//для него длина структуры BITMAPINFO заявлена
	//длинной в 40 байт
	Если Длина_BITMAPINFO <> 40 Тогда
		Возврат "Выбранный файл является файлом bitmap неподходящей версии. Для чтения доступна только вер. 3.";
	КонецЕсли;
	
	//читаем BITMAPINFO
	//вычитаем из длины структуры 4 байта т.к. выше мы их уже считали 
	//для определения длины
	Буфер_BITMAPINFO = ЧтениеДанных.ПрочитатьВБуферДвоичныхДанных(Длина_BITMAPINFO - 4);
	
	//расшифровка структуры 3й версии
	//12	04	4	biWidth Ширина растра в пикселях. Указывается целым числом со знаком. Ноль и отрицательные не документированы.
	//16	08	4	biHeight Целое число со знаком, содержащее два параметра: высота растра в пикселях (абсолютное значение числа) и порядок следования строк в двумерных массивах (знак числа). Нулевое значение не документировано.
	//1A	0C	2	biPlanes В BMP допустимо только значение 1. Это поле используется в значках и курсорах Windows.
	//1C	0E	2	biBitCount Количество бит на пиксель (список поддерживаемых смотрите в отдельном разделе ниже).
	//1E	10	4	biCompression Указывает на способ хранения пикселей (см. в разделе ниже).
	//22	14	4	biSizeImage Размер пиксельных данных в байтах. Может быть обнулено если хранение осуществляется двумерным массивом.
	//26	18	4	biXPelsPerMeter Количество пикселей на метр по горизонтали и вертикали (см. раздел «Разрешение изображения» данной статьи).
	//2A	1C	4	biYPelsPerMeter
	//2E	20	4	biClrUsed Размер таблицы цветов в ячейках.
	//32	24	4	biClrImportant Количество ячеек от начала таблицы цветов до последней используемой (включая её саму).
	
	//мы ведь ЧтениеДанных продолжили считывать в новый буфер
	//адресация теперь в пределах этого буфера (или другими словами - в пределах структуры BITMAPINFO)
	ШиринаРастра = Буфер_BITMAPINFO.ПрочитатьЦелое32(0);
	ВысотаРастра = Буфер_BITMAPINFO.ПрочитатьЦелое32(4);
	Уровень = Буфер_BITMAPINFO.ПрочитатьЦелое16(8);
	БитНаПиксель = Буфер_BITMAPINFO.ПрочитатьЦелое16(10);
	Компрессия = Буфер_BITMAPINFO.ПрочитатьЦелое32(12);
	БайтПикселей = Буфер_BITMAPINFO.ПрочитатьЦелое32(16);
	ПикселейНаМетрГоризонт = Буфер_BITMAPINFO.ПрочитатьЦелое32(20);
	ПикселейНаМетрВертикаль = Буфер_BITMAPINFO.ПрочитатьЦелое32(24);
	РазмерТаблицыЦветов = Буфер_BITMAPINFO.ПрочитатьЦелое32(28);
	ЯчеекТаблицыЦветов = Буфер_BITMAPINFO.ПрочитатьЦелое32(32);
		
	//выведем подробное описание считанного
	стрПредставление = "Размер файла: %1 байт
	|Сигнатура: %2
	|Положение массива пикселей: %3
	|Длина структуры BITMAPINFO: %4 байт
	|Ширина растра: %5 px
	|Высота растра: %6 px
	|Уровень: %7
	|Бит на пиксель: %8 px
	|Компрессия: %9
	|Размер пикселей: %A байт
	|Пикселей на метр по горизонтали: %B px
	|Пикселей на метр по вертикали: %C  px
	|Размер таблицы цветов: %D байт
	|Ячеек в таблице цветов: %F ";
	
	ОписаниеФайла = ПодставитьПараметрыВСтроку(стрПредставление, РазмерФайлБайт, Сигнатура, ПоложениеМассиваПикселей,
											   Длина_BITMAPINFO, ШиринаРастра, ВысотаРастра, Уровень, БитНаПиксель,
											   Компрессия, БайтПикселей, ПикселейНаМетрГоризонт, ПикселейНаМетрВертикаль,
											   РазмерТаблицыЦветов, ЯчеекТаблицыЦветов);
											   
	//между структурами файла и массивом самих пикселей может быть 
	//не задействованный промежуток
	//высчитаем его исходя из длины структур
	ЧтениеДанных.Пропустить(ПоложениеМассиваПикселей - (14 + Длина_BITMAPINFO));
	//теперь читаем поток до конца
	БуферПикселей = ЧтениеДанных.ПрочитатьВБуферДвоичныхДанных();
	ВывестиПотокНаКанвуТабДок(БуферПикселей, ШиринаРастра, ВысотаРастра, БитНаПиксель);
		
	ЧтениеДанных.Закрыть();
		
КонецФункции

Процедуру вывода результата в ТабДок тоже приведу... Дело в том, что в bmp при количестве пикселей по горизонтали, не кратному 4 байтам, строка пикселей дополняется нулями. При выводе это надо учитывать, иначе изображение съедет по диагонали:

вот она:

&НаКлиенте
Функция ВывестиПотокНаКанвуТабДок(БуферПикселей, ШиринаКанвы, ВысотаКанвы, БитНаПиксель)
		
	//рассчитаем длину строки в байт, т.к. для bmp
	//строки не кратные четрым байтам заполняются
	//не используемыми значениями - их нужно отсечь
	
	ДействительныхБайт = ШиринаКанвы * 3;
	
	ДлинаСтрокиБайт = Цел((ШиринаКанвы * 3) / 4)  * 4;
	ДлинаСтрокиБайт = ?(ДлинаСтрокиБайт < ДействительныхБайт, ДлинаСтрокиБайт + 4, ДлинаСтрокиБайт);
	БайтНаДополнениеСтроки = ДлинаСтрокиБайт - (ШиринаКанвы * 3);
	
	КурсорПикселя = -1;                     
	КоординатаПикселя_R = ВысотаКанвы;
	Пока КоординатаПикселя_R > 0 Цикл
			
		Для КоординатаПикселя_C = 1 По ШиринаКанвы Цикл
									
			ИмяПикселя = "R" + Формат(КоординатаПикселя_R, "ЧН=; ЧГ=") + "C" + Формат(КоординатаПикселя_C, "ЧН=; ЧГ=");
			Пиксель = Канва.Область(ИмяПикселя);
			Пиксель.ШиринаКолонки = 0.3;
			Пиксель.ВысотаСтроки = 1;
			
			КурсорПикселя = КурсорПикселя +1;
			ЦветB = БуферПикселей[КурсорПикселя];
			
			КурсорПикселя = КурсорПикселя +1;
			ЦветG = БуферПикселей[КурсорПикселя];
			
			КурсорПикселя = КурсорПикселя +1;
			ЦветR = БуферПикселей[КурсорПикселя];
			
			Пиксель.ЦветФона = Новый Цвет(ЦветR, ЦветG, ЦветB);		
			
			//смещаем курсор на размер пустых байт
			Если КоординатаПикселя_C % ШиринаКанвы = 0 Тогда
				КурсорПикселя = КурсорПикселя + БайтНаДополнениеСтроки;
			КонецЕсли;

		КонецЦикла;
		
		КоординатаПикселя_R = КоординатаПикселя_R - 1;
		
	КонецЦикла;

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

В следующий раз нарисуем битмап, думаю, это опять будет картинка штрихкод EAN-13. Но когда дойдут руки до новой поделки - пока не знаю(

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

PSS. Тестовые картинки с лого Infostart - изображения Infostart - на всякий случай)

См. также

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен и синхронизацию в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

25080 руб.

12.06.2017    138321    764    292    

405

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УПП 1.3 (1.3.230.x) и БП 3.0 (3.0.156.x). Правила подходят для версии ПРОФ и КОРП.

28000 руб.

15.12.2021    21913    144    40    

104

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос данных из ERP в БП 3 | из КА 2 в БП 3 | из УТ 11 в БП 3 | из ЕРП в БП 3 | В продаже с 2019г. | Воспользовались более 176 предприятий! | Сэкономьте время - используйте готовое решение для перехода! | Перенос разработан в формате КД 2 (правила конвертации данных) | Переносятся все возможные виды документов, начальных остатков и нормативно-справочная информация| Можно опционально выгружать каждую пару "номенклатура+характеристика" как отдельную номенклатуру | Есть выгрузка настроек счетов учета и зарплатных данных из ERP / КА 2 | Можно проверить на вашем сервере перед покупкой, обращайтесь!

45650 руб.

15.04.2019    70484    174    146    

117

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист Платформа 1С v8.3 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 Бухгалтерский учет Управленческий учет Платные (руб)

Переход и перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:ERP Управление предприятием 2.5 и 1С:Комплексную автоматизацию 2.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УПП 1.3 (1.3.227.x), ERP 2.5 (2.5.16.x), КА 2.5 (2.5.16.x) .

28000 руб.

24.06.2020    62450    51    27    

81

SALE! %

Перенос данных 1C Взаиморасчеты Оптовая торговля Логистика, склад и ТМЦ Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Управление торговлей 10 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Управленческий учет Платные (руб)

Можно проверить до покупки, оставьте заявку! Воспользовались более 268 компаний! Перенос в продаже с 2015г., и мы постоянно работаем над его развитием. Перенос данных из УТ 10.3 в УТ 11 | из УТ 10.3 в КА 2 | из УТ 10.3 в ERP. Предлагаем качественное и проверенное временем решение для перехода с УТ 10.3. Можно перенести начальные остатки, нормативно-справочную информацию и все возможные документы. При выгрузке можно установить отбор по периоду, организациям и складам. При выходе новых релизов конфигураций 1C оперативно выпускаем обновление переноса данных.

45650 27000 руб.

24.04.2015    192607    143    241    

274

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

В продаже с 2015 года | Воспользовались более 287 предприятий! | Перенос данных из УПП 1.3 в БП 3.0 | из КА 1.1 в БП 3.0 | Переносятся документы, начальные остатки и вся справочная информация | Сэкономьте свое время - используйте готовое решение для перехода! | Есть фильтр по организации и множество других параметров выгрузки | Поддерживается несколько сценариев работы: как первичный полный перенос, так и перенос только новых документов | Перенос данных возможен в "1С: Бухгалтерия 3.0" версии ПРОФ, КОРП или базовую | Переход с "1С: УПП1.3" / "1С:КА 1.1" на "1С:БП3.0" с помощью правил конвертации будет максимально комфортным! | Можно бесплатно проверить перенос на вашем сервере!

39500 руб.

25.02.2015    169826    294    253    

374

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Платформа 1C v8.2 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Управление производственным предприятием Россия Платные (руб)

Регулярный обмен, выгрузка, перенос из КА 1.1, УПП 1.3, УТ 10.3 для обмена с любыми конфигурациями, поддерживающими обмен в формате EnterpriseData (КД3) - БП 3.0, ERP, КА 2, УТ 11, Розница 2, УНФ 1.6 и другими. Правила для старых и доработанных конфигураций не требуют синхронного обновления и совместимы с новыми и будущими конфигурациями. Обмен по расписанию, через папку, FTP, почту.

14580 руб.

18.02.2016    184667    573    509    

516

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 10 1С:Управление торговлей 11 Россия Управленческий учет Платные (руб)

Перенос данных из 1С:Управление торговлей 10.3 в 1С:Управление торговлей 11.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила проверены на конфигурациях УТ 10.3.87.x и УТ 11.5.16.x

28000 руб.

23.07.2020    48538    208    64    

170
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Brawler 457 20.04.17 08:27 Сейчас в теме
1С "любит" нас.
Класс "ОбработкаКартинок" вообще детский... две операции, поворот и обрезка лишнего...
Ни размера изображения не узнать, ни этот самый размер изменить...
Ну и хоть какой нить доступ к аналогу канвы не помешал бы.
Интересно, что их останавливает...
2. premierex 204 20.04.17 09:56 Сейчас в теме
(1) Наверное, не хочет 1С превращать платформу в аналог Photoshop'а )
user774630; +1 Ответить
4. Brawler 457 20.04.17 11:39 Сейчас в теме
(2) да ей до фотошопа рости как до края галактики...
3. v3rter 20.04.17 10:44 Сейчас в теме
Из внешних утилит мне больше всего понравился портированный с линукса консольный ImageMagick https://ru.wikipedia.org/wiki/ImageMagick
правда несколько проблемный из-за совпадения имени основной утилиты convert.exe с одноименной консольной командой windows, то есть или переименовывать или запускать с полным путем
5. Mr.Rm 23.06.17 11:13 Сейчас в теме
Похоже, вот тут опечатка:
|Ячеек в таблице цветов: %F "

Должно быть:
|Ячеек в таблице цветов: %E "
6. Mopo3 332 29.06.17 10:19 Сейчас в теме
Небольшая оптимизация кода. А то на больших размерах тормозит...

Вместо:
Пиксель.ШиринаКолонки = 0.3;
Пиксель.ВысотаСтроки = 1;

которые выполняются в цикле лучше сделать перед циклом:
Канва = Новый ТабличныйДокумент;
всяОбласть = Канва.Область(1,1,ВысотаКанвы,ШиринаКанвы);
всяОбласть.ШиринаКолонки = 0.3;
всяОбласть.ВысотаСтроки = 1;
всяОбласть.АвтоВысотаСтроки = Ложь;

Ускорение процентов на 25.


Также лучше вместо:
ИмяПикселя = "R" + Формат(КоординатаПикселя_R, "ЧН=; ЧГ=") + "C" + Формат(КоординатаПикселя_C, "ЧН=; ЧГ=");
Пиксель = Канва.Область(ИмяПикселя);

сделать:
Пиксель = Канва.Область(КоординатаПикселя_R,КоординатаПикселя_C,КоординатаПикселя_R,КоординатаПикселя_C);

Ускорение еще процентов на 10.



И еще интересное наблюдение, может кому пригодится...
Понадобилось мне вывести объект ГеографическаяСхема в ТабДок. Как раз воспользовался алгоритмом Автора. Но, выявилась проблема. При выполгении ГеографическаяСхема.ПолучитьКартинку() картинка получается с параметром БитНаПиксель = 32. А данный алгоритм корректно отображает картинку только если у нее БитНаПиксель = 24. Соответственно для обработки картинки из ГеоСхемы я применил следующий алгоритм:
_картинкаСхемы = ГеографическаяСхема.ПолучитьКартинку(100,100,ФорматКартинки.BMP);

ОбработкаКартинок = Новый ОбработкаКартинок;
_картинкаСхемы = ОбработкаКартинок.Повернуть(_картинкаСхемы,0); //так нужно чтобы сделать БитНаПиксель 24, а не 32 как получается изначально

_картинкаСхемы = _картинкаСхемы.Преобразовать(ФорматКартинки.BMP);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("BMP");
_картинкаСхемы.Записать(ИмяВременногоФайла);

В результате получается картинка нужного формата, и она корректно отображается на ТабДок.
7. kot-stas 103 04.08.17 16:52 Сейчас в теме
(6) Давненько не заглядывал сюда. По поводу оптимизации спасибо конечно) согласен, так правильнее и быстрее. В свое оправдание хочу сказать, что обработка писалась исключительно! в образовательных целях и код скорее написан для читаемости неподготовленным человеком, нежели с целью реального использования.
А тот факт, что код получил реальное применение (хоть и с доработками) - это вдвойне приятно ;)

На счет глубины цвета - давно было, не помню наверняка, но по моему достаточно было просто переписать процедуру вывода. Сигнатуры, адреса ключевых структур и их длина для 3й версии вне зависимости от глубины цвета по моему не меняются. Но подробнее конечно по ссылке на Вики, там все достаточно подробно).
8. starik-2005 3062 04.08.17 23:14 Сейчас в теме
Как-то делал на assembler'e в детстве вьювер PCX-картинок - 250 с чем-то байт занимало (это была полноценная COM-утилита, запускаемая из командной строки и выводившая файл на экран, переключаясь в VESA-режим 800х600х24). На 1С-е подобные велосипеды бессмысленны от слова "совсем". Вот если бы Вы JPEG или PNG прочитали - это было бы интересно, ибо в них какая-никакая математика есть. Даже в PCX она есть, а в BMP нет ничего - это тупой битмап (карта битов).
9. kot-stas 103 06.08.17 18:00 Сейчас в теме
(8) А зачем здесь эта информация? Или мы здесь *уями меряемся кто в детстве круче поделки делал? Статья в образовательных целях написана, вполне достаточна для представления о том, что представляет из себя работа с буфером двоичных данных и том как устроен bmp (хоть и не сложно, согласен)... Или когда только ленивый не выложил новую счет фактуру сюда - это нормально, а когда пусть и на не сложных примерах, пусть без особой практической пользы пишутся обзорные статьи про тот или иной функционал платформы - это не гут и лучше рефлексировать на свои столь же бесполезные поделки из детства?
10. starik-2005 3062 06.08.17 20:38 Сейчас в теме
(9) у меня все равно длиннее, если мериться. А если о функционале, то я и говорю, что примитивные примеры, конечно, не плохи сами по себе, но с PNG и JPEG было бы куда интереснее.
11. kot-stas 103 07.08.17 12:17 Сейчас в теме
(10) Ну вот и напишите, а то с длинной набитой на котах в отчетах трудно меряться)))
Оставьте свое сообщение