Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> VHDL

Чтение BMP-изображений в VHDL-тестбенчах с помощью TEXTIO

При работе с VHDL-тестбенчами простейший способ импорта изображения — использование растрового формата BMP. BMP-файлы нативно поддерживаются Windows и предоставляют сырые пиксельные данные без сжатия, что идеально для симуляции.

Эта статья объясняет, как прочитать бинарный BMP-файл, сохранить его пиксельные данные в динамической памяти, подать их в VHDL DUT и записать обработанное изображение обратно в новый BMP-файл. Пример DUT выполняет преобразование в оттенки серого, но техника применима к любому пиксельно-ориентированному модулю обработки.

Часть серии TEXTIO:

Почему BMP — оптимальный формат для VHDL

JPEG и PNG повсюду в вебе, но оба используют сжатие. JPEG с потерями, PNG без потерь; оба добавляют слой сложности, когда тестбенч должен обращаться к пиксельным данным напрямую. BMP, с другой стороны, хранит данные изображения как несжатую растровую графику, поэтому каждый пиксель представлен сырыми RGB-байтами. Это устраняет необходимость в коде декомпрессии на VHDL и гарантирует детерминированное время симуляции.

Обычные редакторы изображений, такие как Photoshop или GIMP, загружают изображения в память как растровые данные внутренне. Для VHDL ручная конвертация исходного изображения в BMP (или через скрипт) — самый прямой подход.

Подготовка BMP-файла

Используйте Windows Paint для обеспечения согласованной структуры файла:

  1. Откройте изображение.
  2. Выберите File > Save As.
  3. Выберите 24‑bit Bitmap (*.bmp; *.dib) и сохраните.

Этим методом заголовок файла всегда будет 54-байтным вариантом BITMAPINFOHEADER с пиксельным форматом RGB24. Следующая таблица перечисляет поля заголовка, которые мы читаем.

Offset (Dec)Size (B)Expected (Hex)Description
0242 4DID field
10454 (36 00 00 00)Pixel array offset
14440 (28 00 00 00)Header size
184Read valueImage width in pixels
224Read valueImage height in pixels
26101Number of color planes
28118Number of bits per pixel

Только зеленые поля обязательны; остальные служат проверками здравого смысла.

Тестовый случай

Ниже приведен минимальный DUT в оттенках серого, принимающий 24-битный RGB-вход и выводящий соответствующее значение яркости, закодированное обратно в RGB. Модуль чисто комбинационный, такт не требуется.

entity grayscale is port ( r_in : in std_logic_vector(7 downto 0); g_in : in std_logic_vector(7 downto 0); b_in : in std_logic_vector(7 downto 0); r_out : out std_logic_vector(7 downto 0); g_out : out std_logic_vector(7 downto 0); b_out : out std_logic_vector(7 downto 0) ); end grayscale; 

Для полноты, полный исходный проект (включая 1000×1000 пикселей BMP Boeing 747) доступен для скачивания, указав email в связанной форме.

Импорт TEXTIO

В начале вашего VHDL-файла добавьте:

use std.textio.all; use std.env.finish;

Эти объявления требуют VHDL‑2008 или новее.

Пользовательские типы для хранения изображения

Определите следующие типы в декларативной области вашего тестбенча:

type header_type is array (0 to 53) of character; type pixel_type is record red : std_logic_vector(7 downto 0); green : std_logic_vector(7 downto 0); blue : std_logic_vector(7 downto 0); end record; type row_type is array (integer range <>) of pixel_type; type row_pointer is access row_type; type image_type is array (integer range <>) of row_pointer; type image_pointer is access image_type;

Эти динамические структуры данных позволяют тестбенчу вмещать изображения любого размера без статических ограничений массивов.

Инстанциация DUT

signal r_in, g_in, b_in : std_logic_vector(7 downto 0); signal r_out, g_out, b_out : std_logic_vector(7 downto 0); begin DUT : entity work.grayscale port map ( r_in => r_in, g_in => g_in, b_in => b_in, r_out => r_out, g_out => g_out, b_out => b_out ); 

Чтение заголовка BMP

Процесс начинается с загрузки 54-байтового заголовка в переменную header и проверки ключевых полей с операторами assert. Эта защита предотвращает случайное использование неподдерживаемого формата файла.

for i in header_type'range loop read(bmp_file, header(i)); end loop; -- Basic sanity checks assert header(0) = 'B' and header(1) = 'M' report "First two bytes are not ""BM"". This is not a BMP file" severity failure; assert character'pos(header(10)) = 54 and character'pos(header(11)) = 0 and character'pos(header(12)) = 0 and character'pos(header(13)) = 0 report "Pixel array offset is not 54 bytes" severity failure; assert character'pos(header(14)) = 40 and character'pos(header(15)) = 0 and character'pos(header(16)) = 0 and character'pos(header(17)) = 0 report "DIB header size is not 40 bytes, is this a Windows BMP?" severity failure; assert character'pos(header(26)) = 1 and character'pos(header(27)) = 0 report "Color planes is not 1" severity failure; assert character'pos(header(28)) = 24 and character'pos(header(29)) = 0 report "Bits per pixel is not 24" severity failure;

После валидации извлекаются ширина и высота изображения:

image_width := character'pos(header(18)) + character'pos(header(19)) * 2**8 + character'pos(header(20)) * 2**16 + character'pos(header(21)) * 2**24; image_height := character'pos(header(22)) + character'pos(header(23)) * 2**8 + character'pos(header(24)) * 2**16 + character'pos(header(25)) * 2**24; report "image_width: " & integer'image(image_width) & ", image_height: " & integer'image(image_height);

Чтение пиксельных данных

Каждая строка BMP дополняется до кратности четырём байтам. Вычислите отступ на строку и выделите динамическое хранилище для изображения.

padding := (4 - image_width*3 mod 4) mod 4; image := new image_type(0 to image_height - 1); for row_i in 0 to image_height - 1 loop row := new row_type(0 to image_width - 1); for col_i in 0 to image_width - 1 loop read(bmp_file, char); row(col_i).blue := std_logic_vector(to_unsigned(character'pos(char), 8)); read(bmp_file, char); row(col_i).green := std_logic_vector(to_unsigned(character'pos(char), 8)); read(bmp_file, char); row(col_i).red := std_logic_vector(to_unsigned(character'pos(char), 8)); end loop; for i in 1 to padding loop read(bmp_file, char); end loop; -- discard padding image(row_i) := row; end loop;

Тестирование DUT

Подайте каждый пиксель в DUT, подождите небольшой дельта-цикл и захватите выход в оттенках серого.

for row_i in 0 to image_height - 1 loop row := image(row_i); for col_i in 0 to image_width - 1 loop r_in <= row(col_i).red; g_in <= row(col_i).green; b_in <= row(col_i).blue; wait for 10 ns; row(col_i).red := r_out; row(col_i).green := g_out; row(col_i).blue := b_out; end loop; end loop;

Запись выходного BMP

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

for i in header_type'range loop write(out_file, header(i)); end loop; for row_i in 0 to image_height - 1 loop row := image(row_i); for col_i in 0 to image_width - 1 loop write(out_file, character'val(to_integer(unsigned(row(col_i).blue)))); write(out_file, character'val(to_integer(unsigned(row(col_i).green)))); write(out_file, character'val(to_integer(unsigned(row(col_i).red)))); end loop; deallocate(row); for i in 1 to padding loop write(out_file, character'val(0)); end loop; end loop; deallocate(image); file_close(bmp_file); file_close(out_file); report "Simulation done. Check ""out.bmp"" image."; finish; end process;

Результирующее изображение

Сгенерированный файл out.bmp показывает версию в оттенках серого исходного изображения Boeing 747. JPEG-превью отображено в статье; полный BMP-файл доступен через форму скачивания.

Дальнейшие соображения

VHDL

  1. Голография: от нобелевского открытия Габора к хранилищам данных будущего
  2. Освоение операторов using в C#: импорт, псевдонимы и статические директивы
  3. Работа с файлами в C: мастерство ввода-вывода с fopen, fprintf, fread и fseek
  4. Мастерство файловых операций в Java с java.io: создание, чтение, запись и удаление
  5. Инициализация блочной памяти FPGA из текстовых файлов с помощью библиотеки TEXTIO в VHDL
  6. Чтение файлов в Java с BufferedReader — Практическое руководство с примерами
  7. Python JSON: кодирование, декодирование и работа с файлами — практическое руководство
  8. Работа с файлами в Verilog: открытие, чтение, запись и закрытие
  9. Заголовочные файлы в C: типы, подключение и лучшие практики
  10. Научный центр NASA Langley представляет передовительную пленоптическую камеру для 3D-цветовой визуализации