Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

BMP-Bitmap-Bilder in VHDL-Testbenches mit TEXTIO einlesen

Bei der Arbeit mit VHDL-Testbenches ist der einfachste Weg, ein Bild zu importieren, das BMP-Rastergrafikformat. BMP-Dateien werden nativ von Windows unterstützt und enthalten unkomprimierte Rohpixel-Daten, was sie ideal für Simulationen macht.

Dieser Artikel erklärt, wie man eine binäre BMP-Datei einliest, ihre Pixeldaten im dynamischen Speicher speichert, sie an ein VHDL-DUT übergibt und das verarbeitete Bild in eine neue BMP-Datei zurückschreibt. Das Beispiel-DUT führt eine Graustufenkonvertierung durch, die Technik gilt jedoch für jedes pixelweise Verarbeitungsmodul.

Teil einer TEXTIO-Serie:

Warum BMP das optimale Format für VHDL ist

JPEG und PNG sind im Web allgegenwärtig, aber beide nutzen Kompression. JPEG ist verlustbehaftet, PNG verlustfrei; beide fügen eine Komplexitätsebene hinzu, wenn ein Testbench direkt auf Pixeldaten zugreifen muss. BMP speichert Bilddaten als unkomprimierte Rastergrafik, sodass jedes Pixel durch rohe RGB-Bytes repräsentiert wird. Das eliminiert die Notwendigkeit für Dekompressionscode in VHDL und garantiert deterministische Simulationszeit.

Gängige Bildeditoren wie Photoshop oder GIMP laden Bilder intern als Rasterdaten. Für VHDL ist die manuelle (oder per Skript) Konvertierung des Quellbildes in BMP der direkteste Ansatz.

BMP-Datei vorbereiten

Nutzen Sie Windows Paint für ein konsistentes Dateilayout:

  1. Bild öffnen.
  2. Datei > Speichern unter wählen.
  3. 24-Bit Bitmap (*.bmp; *.dib) auswählen und speichern.

Mit dieser Methode hat der Dateiheader immer die 54-Byte-BITMAPINFOHEADER-Variante mit RGB24-Pixelformat. Die folgende Tabelle listet die Header-Felder auf, die wir einlesen.

Offset (Dez)Größe (B)Erwartet (Hex)Beschreibung
0242 4DID-Feld
10454 (36 00 00 00)Pixel-Array-Offset
14440 (28 00 00 00)Header-Größe
184Gelesener WertBildbreite in Pixeln
224Gelesener WertBildhöhe in Pixeln
26101Anzahl Farbebenen
28118Bits pro Pixel

Nur die grün markierten Felder sind essenziell; der Rest dient als Plausibilitätsprüfung.

Der Testfall

Unten steht ein minimales Graustufen-DUT, das 24-Bit-RGB-Eingang akzeptiert und den entsprechenden Luminanzwert wieder in RGB kodiert ausgibt. Das Modul ist rein kombinatorisch, kein Takt erforderlich.

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; 

Für Vollständigkeit ist der vollständige Projektquellcode (inklusive 1000×1000 Pixel Boeing 747 BMP) über das verlinkte Formular per E-Mail-Adresse erhältlich.

TEXTIO importieren

Fügen Sie am Anfang Ihrer VHDL-Datei hinzu:

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

Diese Deklarationen erfordern VHDL-2008 oder neuer.

Benutzerdefinierte Typen für Bildspeicherung

Definieren Sie folgende Typen im deklarativen Bereich Ihres Testbenchs:

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;

Diese dynamischen Datenstrukturen erlauben dem Testbench, Bilder beliebiger Größe ohne statische Array-Grenzen zu handhaben.

DUT instanziieren

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-Header einlesen

Der Prozess beginnt damit, den 54-Byte-Header in eine header-Variable zu laden und Schlüsselwerte mit assert-Statements zu validieren. Diese Absicherung verhindert die versehentliche Nutzung eines nicht unterstützten Dateiformats.

for i in header_type'range loop read(bmp_file, header(i)); end loop; -- Basis-Plausibilitätsprüfungen 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;

Nach Validierung werden Bildbreite und -höhe extrahiert:

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);

Pixeldaten einlesen

Jede BMP-Zeile wird auf ein Vielfaches von vier Bytes gepadded. Berechnen Sie das Padding pro Zeile und allozieren Sie dynamischen Speicher für das Bild.

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; -- Padding verwerfen image(row_i) := row; end loop;

DUT testen

Führen Sie jeden Pixel in das DUT ein, warten Sie einen kleinen Delta-Zyklus, und erfassen Sie die Graustufen-Ausgabe.

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;

Ausgabe-BMP schreiben

Zuerst den erhaltenen Header schreiben. Dann die Pixeldaten zeilenweise serialisieren, Padding hinzufügen. Schließlich dynamischen Speicher freigeben und Dateien schließen.

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;

Ergebnisbild

Die generierte out.bmp-Datei zeigt die Graustufenversion des ursprünglichen Boeing-747-Bildes. Eine JPEG-Vorschau wird im Artikel angezeigt; die vollständige BMP-Datei ist über das Download-Formular erhältlich.

Weitere Überlegungen

VHDL

  1. Holografie entmystifiziert: Von Gabors Nobelpreis-Erfindung bis zum Datenspeicher der Zukunft
  2. C# using-Anweisungen meistern: Importe, Aliase und statische Direktiven
  3. C-Dateiverwaltung: I/O mit fopen, fprintf, fread & fseek meistern
  4. Java-Dateioperationen mit java.io meistern – Erstellen, Lesen, Schreiben & Löschen
  5. FPGA Block RAM aus Textdateien mit VHDLs TEXTIO-Bibliothek initialisieren
  6. Dateien in Java mit BufferedReader lesen – Praktischer Leitfaden mit Beispielen
  7. Python JSON: Encoding, Decoding und Datei-Handling – Ein praktischer Leitfaden
  8. Datei-E/A in Verilog meistern: Öffnen, Lesen, Schreiben und Schließen
  9. C-Header-Dateien verstehen: Typen, Verwendung und Best Practices
  10. NASA Langley Research Center stellt fortschrittliche Plenoptik-Kamera für 3D-Farbbildgebung vor