Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> VHDL

Lire des images bitmap BMP dans les bancs de test VHDL avec TEXTIO

Lorsqu'on travaille avec des bancs de test VHDL, la façon la plus simple d'importer une image est d'utiliser le format graphique raster BMP. Les fichiers BMP sont nativement supportés par Windows, et ils exposent les données brutes des pixels sans compression, les rendant idéaux pour la simulation.

Cet article explique comment lire un fichier BMP binaire, stocker ses données de pixels en mémoire dynamique, les fournir à un DUT VHDL, et écrire l'image traitée dans un nouveau fichier BMP. Le DUT exemple effectue une conversion en niveaux de gris, mais la technique s'applique à tout module de traitement pixel par pixel.

Partie d'une série TEXTIO :

Pourquoi le BMP est le format optimal pour VHDL

JPEG et PNG sont omniprésents sur le web, mais les deux emploient la compression. JPEG est avec pertes, PNG est sans pertes ; les deux ajoutent une couche de complexité quand un banc de test doit accéder aux données de pixels directement. Le BMP, en revanche, stocke les données d'image comme des graphiques raster non compressés, donc chaque pixel est représenté par des octets RGB bruts. Cela élimine le besoin de code de décompression en VHDL et garantit un temps de simulation déterministe.

Les éditeurs d'images courants comme Photoshop ou GIMP chargent les images en mémoire comme des données raster en interne. Pour VHDL, convertir l'image source en BMP manuellement (ou via un script) est l'approche la plus directe.

Préparation du fichier BMP

Utilisez Windows Paint pour assurer une disposition de fichier cohérente :

  1. Ouvrez l'image.
  2. Sélectionnez Fichier > Enregistrer sous.
  3. Choisissez Bitmap 24 bits (*.bmp; *.dib) et enregistrez.

Avec cette méthode, l'en-tête de fichier sera toujours la variante BITMAPINFOHEADER de 54 octets avec un format de pixel RGB24. Le tableau suivant liste les champs d'en-tête que nous lisons.

Offset (Déc)Taille (O)Attendu (Hex)Description
0242 4DChamp ID
10454 (36 00 00 00)Décalage tableau de pixels
14440 (28 00 00 00)Taille d'en-tête
184Lire la valeurLargeur de l'image en pixels
224Lire la valeurHauteur de l'image en pixels
26101Nombre de plans de couleur
28118Nombre de bits par pixel

Seuls les champs ombragés en vert sont essentiels ; les autres servent de vérifications de bon sens.

Le cas de test

Voici un DUT de conversion en niveaux de gris minimal qui accepte une entrée RGB 24 bits et sort la valeur de luminance correspondante réencodée en RGB. Le module est purement combinatoire, donc aucune horloge n'est requise.

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; 

Pour la complétude, le code source complet du projet (incluant un BMP Boeing 747 de 1000×1000 pixels) est disponible en téléchargement en fournissant une adresse e-mail sur le formulaire lié.

Importation de TEXTIO

Au sommet de votre fichier VHDL, ajoutez :

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

Ces déclarations requièrent VHDL-2008 ou plus récent.

Types personnalisés pour le stockage d'image

Définissez les types suivants dans la région déclarative de votre banc de test :

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;

Ces structures de données dynamiques permettent au banc de test d'accommoder des images de toute taille sans limites de tableau statique.

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

Lecture de l'en-tête BMP

Le processus commence par charger l'en-tête de 54 octets dans une variable header et valider les champs clés avec des instructions assert. Cette garde empêche l'utilisation accidentelle d'un format de fichier non supporté.

for i in header_type'range loop read(bmp_file, header(i)); end loop; -- Vérifications de base 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;

Après validation, la largeur et la hauteur de l'image sont extraites :

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

Lecture des données de pixels

Chaque ligne BMP est remplie jusqu'à un multiple de quatre octets. Calculez le remplissage par ligne et allouez un stockage dynamique pour l'image.

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; -- ignorer le remplissage image(row_i) := row; end loop;

Test du DUT

Alimentez chaque pixel dans le DUT, attendez un petit cycle delta, et capturez la sortie en niveaux de gris.

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;

Écriture du BMP de sortie

D'abord, écrivez l'en-tête préservé. Ensuite, sérialisez les données de pixels ligne par ligne, en ajoutant le remplissage si nécessaire. Finalement, nettoyez la mémoire dynamique et fermez les fichiers.

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;

Image résultante

Le fichier out.bmp généré montre la version en niveaux de gris de l'image originale du Boeing 747. Un aperçu JPEG est affiché dans l'article ; le fichier BMP complet est disponible via le formulaire de téléchargement.

Considérations supplémentaires

VHDL

  1. Maîtriser les directives using C# : Imports, alias et directives static
  2. Gestion des fichiers en C : Maîtriser les E/S avec fopen, fprintf, fread et fseek
  3. Maîtriser les opérations sur les fichiers Java avec java.io – Création, lecture, écriture et suppression
  4. Initialiser la RAM bloc FPGA depuis des fichiers texte avec la bibliothèque TEXTIO de VHDL
  5. Lecture de Fichiers en Java avec BufferedReader – Guide Pratique avec Exemples
  6. Python JSON : encodage, décodage et gestion de fichiers – Guide pratique
  7. Maîtriser les entrées/sorties de fichiers en Verilog : Ouvrir, Lire, Écrire et Fermer
  8. Comprendre les fichiers d'en-tête C : Types, utilisation et bonnes pratiques
  9. Centre de recherche Langley de la NASA dévoile une caméra plénoptique avancée pour imagerie 3D couleur