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

BMP-Datei-Bitmap-Bild, das mit TEXTIO gelesen wird

Das Konvertieren der Bilddatei in ein Bitmap-Format ist die einfachste Möglichkeit, ein Bild mit VHDL zu lesen. Die Unterstützung für das BMP-Rastergrafik-Bilddateiformat ist in das Microsoft Windows-Betriebssystem integriert. Damit ist BMP ein geeignetes Bildformat zum Speichern von Fotos für die Verwendung in VHDL-Testbenches.

In diesem Artikel erfahren Sie, wie Sie eine binäre Bilddatei wie BMP lesen und die Daten im dynamischen Speicher des Simulators speichern. Wir werden ein beispielhaftes Bildverarbeitungsmodul verwenden, um das Bild in Graustufen umzuwandeln, dies wird unser zu testendes Gerät (DUT) sein. Schließlich schreiben wir die Ausgabe des DUT in ein neues Bild, das wir visuell mit dem Original vergleichen können.

Dieser Blogbeitrag ist Teil einer Reihe über die Verwendung der TEXTIO-Bibliothek in VHDL. Lesen Sie die anderen Artikel hier:

So initialisieren Sie RAM aus einer Datei mit TEXTIO

Stimulus-Datei in Testbench mit TEXTIO eingelesen

Warum Bitmap das beste Format für VHDL ist

Die gängigsten Bilddateiformate im Internet sind JPEG und PNG. Beide verwenden Komprimierung, JPEG ist verlustbehaftet, während PNG verlustfrei ist. Die meisten Formate bieten eine Form der Komprimierung, da dies die Speichergröße des Bildes drastisch reduzieren kann. Während dies für den normalen Gebrauch in Ordnung ist, ist es nicht ideal zum Lesen in einer VHDL-Testbench.

Um ein Bild in Software oder Hardware verarbeiten zu können, müssen Sie Zugriff auf die Pixel-Rohdaten in Ihrer Anwendung haben. Sie möchten die Farb- und Luminanzdaten in einer Byte-Matrix gespeichert haben, dies wird als Bitmap- oder Rastergrafik bezeichnet.

Die meisten bekannten Bildbearbeitungsprogramme wie Photoshop oder GIMP sind rasterbasiert. Sie können eine Vielzahl von Bildformaten öffnen, werden aber alle intern im Editor in Rastergrafiken umgewandelt.

Das geht auch in VHDL, aber das würde einen erheblichen Codierungsaufwand erfordern, da es keine vorgefertigten Lösungen zum Decodieren komprimierter Bilder gibt. Eine bessere Lösung besteht darin, die Testeingabebilder manuell in ein Bitmap-Format wie BMP zu konvertieren oder sie in das Skript einzubinden, das Ihre Testbench startet.

Das BMP-Bilddateiformat

Das BMP-Dateiformat ist auf Wikipedia gut dokumentiert. Dieses Format hat viele verschiedene Varianten, aber wir werden uns auf einige spezifische Einstellungen einigen, die es uns viel einfacher machen werden. Um unsere Eingabebilder zu erstellen, öffnen wir sie in Microsoft Paint, das mit Windows vorinstalliert ist. Dann klicken wir auf Datei→Speichern unter , wählen Sie Dateityp:24-Bit-Bitmap (*bmp; *.dib) aus . Benennen Sie die Datei mit der Endung .bmp und klicken Sie auf Speichern.

Indem wir sicherstellen, dass die Datei so erstellt wird, können wir davon ausgehen, dass der Header immer die 54 Bytes lange BITMAPINFOHEADER-Variante mit Pixelformat RGB24 ist, die auf der Wikipedia-Seite erwähnt wird. Darüber hinaus kümmern wir uns nur um einige wenige ausgewählte Felder innerhalb der Kopfzeile. Die folgende Tabelle zeigt die Header-Felder, die wir lesen werden.

Offset (Dez) Größe (B) Erwartet (Hex) Beschreibung
0 2 „BM“ (42 4D) ID-Feld
10 4 54 (36 00 00 00) Pixel-Array-Offset
14 4 40 (28 00 00 00) Kopfzeilengröße
18 4 Wert lesen Bildbreite in Pixel
22 4 Wert lesen Bildhöhe in Pixel
26 1 1 (01) Anzahl der Farbebenen
28 1 24 (18) Anzahl Bits pro Pixel

Die grün markierten Werte sind die einzigen, die wir uns wirklich ansehen müssen, weil wir wissen, welche Werte in den anderen Header-Feldern zu erwarten sind. Wenn Sie zugestimmt haben, jedes Mal nur Bilder mit vordefinierten festen Abmessungen zu verwenden, können Sie den gesamten Header überspringen und bei Byte-Offset-Nummer 54 innerhalb der BMP-Datei mit dem Lesen beginnen, dort befinden sich die Pixeldaten.

Wir werden trotzdem prüfen, ob die anderen aufgeführten Werte wie erwartet sind. Es ist nicht schwierig, da wir bereits die Überschrift lesen. Es bietet auch einen Schutz vor Benutzerfehlern, falls Sie oder einer Ihrer Kollegen in Zukunft ein Bild mit der falschen Codierung an die Testbench liefern sollten.

Der Testfall

In diesem Blogbeitrag geht es darum, wie man ein Bild aus einer Datei in einer VHDL-Testbench liest, aber der Vollständigkeit halber habe ich ein Beispiel-DUT beigefügt. Wir werden die Pixeldaten durch das DUT streamen, während wir das Bild lesen. Schließlich schreiben wir die Ergebnisse in eine andere BMP-Ausgabedatei, die Sie in Ihrem bevorzugten Bildbetrachter betrachten können.

entity grayscale is
  port (
    -- RGB input
    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);

    -- RGB output
    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; 

Der obige Code zeigt die Entität unseres DUT. Das Graustufenmodul nimmt die 24-Bit-RGB-Daten für ein Pixel als Eingabe und wandelt sie in eine Graustufendarstellung um, die am Ausgang präsentiert wird. Beachten Sie, dass das Ausgabepixel einen Grauton darstellt, der sich immer noch im RGB-Farbraum befindet. Wir konvertieren das BMP nicht in ein Graustufen-BMP, das ein anderes Format hat.

Das Modul ist rein kombinatorisch, es gibt keinen Clock- oder Reset-Eingang. Das Ergebnis erscheint sofort am Ausgang, wenn dem Eingang etwas zugewiesen wird. Der Einfachheit halber verwendet die Umwandlung in Graustufen eine Festkomma-Annäherung des Luma-Werts (Helligkeit) gemäß dem ITU-R BT.2100 RGB-zu-Luma-Codierungssystem.

Sie können den Code für das Graustufenmodul und das gesamte Projekt herunterladen, indem Sie das folgende Formular verwenden.

Das Bild der Boeing 747, das Sie unten sehen, ist unser Beispiel-Eingabebild. Das heißt, es ist nicht das eigentliche BMP-Bild, das in diesen Blog-Beitrag eingebettet ist, das wäre nicht möglich. Es ist eine JPEG-Darstellung des BMP-Bildes, das wir in unserer Testbench lesen werden. Sie können das Original-BMP-Bild anfordern, indem Sie Ihre E-Mail-Adresse in das obige Formular eingeben, und Sie erhalten es sofort in Ihrem Posteingang.

Das Testbild ist 1000 x 1000 Pixel groß. Der in diesem Artikel vorgestellte Code sollte jedoch mit allen Bildabmessungen funktionieren, solange er im BITMAPINFOHEADER 24-Bit-BMP-Format vorliegt. Das Einlesen eines großen Bildes nimmt jedoch viel Simulationszeit in Anspruch, da der Dateizugriff in den meisten VHDL-Simulatoren langsam ist. Dieses Bild ist 2930 kB groß und braucht einige Sekunden zum Laden in ModelSim.

Importieren Sie die TEXTIO-Bibliothek

Um Dateien in VHDL zu lesen oder in Dateien zu schreiben, müssen Sie die TEXTIO-Bibliothek importieren. Stellen Sie sicher, dass Sie die Zeilen aus der folgenden Liste oben in Ihre VHDL-Datei einfügen. Wir müssen auch den finish importieren Schlüsselwort aus dem Standardpaket, um die Simulation zu stoppen, wenn alle Tests abgeschlossen sind.

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

Die obigen Anweisungen erfordern die Verwendung von VHDL-2008 oder neuer.

Benutzerdefinierte Typdeklarationen

Wir werden einige benutzerdefinierte Typen zu Beginn des deklarativen Bereichs unserer Testbench deklarieren. Das Format der Datenstrukturen zum Speichern von Pixeldaten hängt davon ab, welche Art von Eingabe das DUT erwartet. Das Graustufenmodul erwartet drei Bytes, die jeweils eine der Farbkomponenten Rot, Grün und Blau darstellen. Da es jeweils mit einem Pixel arbeitet, können wir den Pixelsatz nach Belieben speichern.

Wie wir aus dem folgenden Code sehen können, deklarieren wir zuerst eine header_type Array, in dem wir alle Header-Daten speichern. Wir werden einige Felder innerhalb des Headers untersuchen, aber wir müssen ihn auch speichern, da wir die verarbeiteten Bilddaten am Ende der Testbench in eine neue Datei schreiben werden. Dann müssen wir den ursprünglichen Header in das Ausgabebild einfügen.

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;

Die zweite Anweisung deklariert einen Datensatz namens pixel_type . Dieser benutzerdefinierte Typ fungiert als Container für die RGB-Daten für ein Pixel.

Schließlich werden die dynamischen Datenstrukturen zum Speichern aller Pixel deklariert. Während row_type ist ein unbeschränktes Array von pixel_type , die row_pointer ist ein Zugriffstyp darauf, ein VHDL-Zeiger. Auf ähnliche Weise konstruieren wir einen uneingeschränkten image_type Array, in dem alle Pixelzeilen gespeichert werden.

Also die image_pointer Typ fungiert als Handle für das vollständige Bild im dynamisch zugewiesenen Speicher.

Instanziieren des DUT

Am Ende des deklarativen Bereichs deklarieren wir die Schnittstellensignale für das DUT, wie unten gezeigt. Die Eingangssignale werden mit _in nachgestellt und die Ausgangssignale mit _out . Dadurch können wir sie sowohl im Code als auch in der Wellenform leicht identifizieren. Das DUT wird am Anfang der Architektur mit den Signalen instanziiert, die durch die Port-Map zugewiesen werden.

signal r_in : std_logic_vector(7 downto 0);
signal g_in : std_logic_vector(7 downto 0);
signal b_in : std_logic_vector(7 downto 0);
signal r_out : std_logic_vector(7 downto 0);
signal g_out : std_logic_vector(7 downto 0);
signal b_out : std_logic_vector(7 downto 0);

begin

DUT :entity work.grayscale(rtl)
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
);

Prozessvariablen und Dateihandles

Wir werden einen einzigen Testbench-Prozess erstellen, der das gesamte Lesen und Schreiben von Dateien enthält. Der deklarative Bereich des Prozesses ist unten dargestellt. Wir beginnen mit der Deklaration eines neuen char_file type, um den Datentyp zu definieren, den wir aus der Eingabebilddatei lesen möchten. Die BMP-Datei ist binär kodiert; deshalb wollen wir mit Bytes arbeiten, dem character Geben Sie VHDL ein. In den nächsten beiden Zeilen verwenden wir den Typ, um eine Eingabe- und eine Ausgabedatei zu öffnen.

process
  type char_file is file of character;
  file bmp_file : char_file open read_mode is "boeing.bmp";
  file out_file : char_file open write_mode is "out.bmp";
  variable header : header_type;
  variable image_width : integer;
  variable image_height : integer;
  variable row : row_pointer;
  variable image : image_pointer;
  variable padding : integer;
  variable char : character;
begin

Als nächstes deklarieren wir eine Variable, die die Header-Daten enthält, sowie zwei Integer-Variablen, die die Breite und Höhe des Bildes enthalten. Danach deklarieren wir einen row Zeiger und ein image Zeiger. Letzteres wird unser Handle für das vollständige Bild sein, sobald es aus der Datei gelesen wurde.

Schließlich deklarieren wir zwei praktische Variablen; padding vom Typ integer und char vom Typ character . Wir werden diese verwenden, um Werte, die wir aus der Datei gelesen haben, vorübergehend zu speichern.

Lesen des BMP-Headers

Zu Beginn des Prozesskörpers lesen wir den gesamten Header aus der BMP-Datei in den header Variable, wie im folgenden Code gezeigt. Der Header ist 54 Bytes lang, aber anstatt den hartcodierten Wert zu verwenden, erhalten wir den zu durchlaufenden Bereich, indem wir auf header_type'range verweisen Attribut. Sie sollten nach Möglichkeit immer Attribute verwenden, um die definierten konstanten Werte an so wenigen Stellen wie möglich zu halten.

  for i in header_type'range loop
    read(bmp_file, header(i));
  end loop;

Dann folgen ein paar Assert-Anweisungen, in denen wir überprüfen, ob einige der Header-Felder wie erwartet sind. Dies ist ein Schutz vor Benutzerfehlern, da wir die gelesenen Werte für nichts verwenden, sondern nur prüfen, ob sie wie erwartet sind. Die erwarteten Werte sind diejenigen, die in dieser Tabelle aufgeführt sind, die weiter oben in diesem Artikel gezeigt wurde.

Der folgende Code zeigt die Assert-Anweisungen, jeweils mit einem report Anweisung, die den Fehler beschreibt, und ein severity failure -Anweisung, um die Simulation zu stoppen, wenn der geltend gemachte Ausdruck false ist . Wir müssen einen erhöhten Schweregrad verwenden, da zumindest mit den Standardeinstellungen in ModelSim nur eine Fehlermeldung ausgegeben und die Simulation fortgesetzt wird.

  -- Check ID field
  assert header(0) = 'B' and header(1) = 'M'
    report "First two bytes are not ""BM"". This is not a BMP file"
    severity failure;

  -- Check that the pixel array offset is as expected
  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 in header is not 54 bytes"
    severity failure;

  -- Check that DIB header size is 40 bytes,
  -- meaning that the BMP is of type BITMAPINFOHEADER
  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 headers size is not 40 bytes, is this a Windows BMP?"
    severity failure;

  -- Check that the number of color planes is 1
  assert character'pos(header(26)) = 1 and
    character'pos(header(27)) = 0
    report "Color planes is not 1" severity failure;

  -- Check that the number of bits per pixel is 24
  assert character'pos(header(28)) = 24 and
    character'pos(header(29)) = 0
    report "Bits per pixel is not 24" severity failure;

Dann lesen wir die Felder Breite und Höhe des Bildes aus der Kopfzeile. Dies sind die einzigen beiden Werte, die wir tatsächlich verwenden werden. Daher ordnen wir sie dem image_width zu und image_height Variablen. Wie wir aus dem folgenden Code sehen können, müssen wir die nachfolgenden Bytes mit der gewichteten Potenz von zwei Werten multiplizieren, um die 4-Byte-Header-Felder in richtige Integer-Werte umzuwandeln.

  -- Read image width
  image_width := character'pos(header(18)) +
    character'pos(header(19)) * 2**8 +
    character'pos(header(20)) * 2**16 +
    character'pos(header(21)) * 2**24;

  -- Read image height
  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);

Schließlich geben wir die gelesene Höhe und Breite mit report an die Simulatorkonsole aus Erklärung.

Lesen der Pixeldaten

Wir müssen herausfinden, wie viele Füllbytes in jeder Zeile vorhanden sind, bevor wir mit dem Einlesen der Pixeldaten beginnen können. Das BMP-Format erfordert, dass jede Reihe von Pixeln auf ein Vielfaches von vier Bytes aufgefüllt wird. Im folgenden Code kümmern wir uns darum mit einer einzeiligen Formel, die den Modulo-Operator für die Bildbreite verwendet.

  -- Number of bytes needed to pad each row to 32 bits
  padding := (4 - image_width*3 mod 4) mod 4;

Wir müssen auch Platz für alle Zeilen von Pixeldaten reservieren, die wir lesen werden. Der image Variable ist ein Zugriffstyp, ein VHDL-Zeiger. Damit es auf einen beschreibbaren Speicherplatz zeigt, verwenden wir den new Schlüsselwort, um Platz für image_height zu reservieren Anzahl der Zeilen im dynamischen Speicher, wie unten gezeigt.

  -- Create a new image type in dynamic memory
  image := new image_type(0 to image_height - 1);

Jetzt ist es an der Zeit, die Bilddaten auszulesen. Die folgende Auflistung zeigt die for-Schleife, die das Array von Pixeln Zeile für Zeile liest. Für jede Zeile reservieren wir Platz für ein neues row_type Objekt, auf das der row zeigt Variable. Dann lesen wir die erwartete Anzahl von Pixeln, zuerst die blaue, dann die grüne und schließlich die rote Farbe. Dies ist die Reihenfolge gemäß dem 24-Bit-BMP-Standard.

  for row_i in 0 to image_height - 1 loop

    -- Create a new row type in dynamic memory
    row := new row_type(0 to image_width - 1);

    for col_i in 0 to image_width - 1 loop

      -- Read blue pixel
      read(bmp_file, char);
      row(col_i).blue :=
        std_logic_vector(to_unsigned(character'pos(char), 8));

      -- Read green pixel
      read(bmp_file, char);
      row(col_i).green :=
        std_logic_vector(to_unsigned(character'pos(char), 8));

      -- Read red pixel
      read(bmp_file, char);
      row(col_i).red :=
        std_logic_vector(to_unsigned(character'pos(char), 8));

    end loop;

    -- Read and discard padding
    for i in 1 to padding loop
      read(bmp_file, char);
    end loop;

    -- Assign the row pointer to the image vector of rows
    image(row_i) := row;

  end loop;

Nach dem Lesen der Nutzdaten für jede Zeile lesen und verwerfen wir die zusätzlichen Füllbytes (falls vorhanden). Schließlich weisen wir am Ende der Schleife die neue dynamische Pixelreihe dem richtigen Slot des image zu Reihe. Wenn die for-Schleife den image beendet Variable sollte Pixeldaten für das gesamte BMP-Bild enthalten.

Testen des DUT

Das Graustufenmodul verwendet nur kombinatorische Logik, sodass wir uns keine Gedanken über Takt- oder Reset-Signale machen müssen. Der folgende Code geht durch jedes Pixel in jeder Zeile, während er die RGB-Werte in die DUT-Eingänge schreibt. Nach dem Zuweisen der Eingangswerte warten wir 10 Nanosekunden, um alle Deltazyklusverzögerungen innerhalb des DUT abwickeln zu lassen. Alle Zeitwerte größer als 0 funktionieren, oder sogar wait for 0 ns; oft genug wiederholt.

  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;

Wenn das Programm aus der Warteanweisung herauskommt, sollten die DUT-Ausgaben die RGB-Werte für die Graustufenfarbe für dieses Pixel enthalten. Am Ende der Schleife lassen wir die DUT-Ausgabe die Pixelwerte ersetzen, die wir aus der Eingabe-BMP-Datei gelesen haben.

Schreiben der BMP-Ausgabedatei

An diesem Punkt sind alle Pixel in image Variable sollte vom DUT manipuliert worden sein. Es ist an der Zeit, die Bilddaten auf den out_file zu schreiben -Objekt, das auf eine lokale Datei mit dem Namen „out.bmp“ zeigt. Im folgenden Code durchlaufen wir jedes Pixel in den Header-Bytes, die wir aus der Eingabe-BMP-Datei gespeichert haben, und schreiben sie in die Ausgabedatei.

  for i in header_type'range loop
    write(out_file, header(i));
  end loop;

Nach dem Header müssen wir die Pixel in der Reihenfolge schreiben, in der wir sie aus der Eingabedatei gelesen haben. Dafür sorgen die beiden verschachtelten for-Schleifen im Listing unten. Beachten Sie, dass wir nach jeder Zeile den deallocate verwenden Schlüsselwort, um den dynamisch zugewiesenen Speicher für jede Zeile freizugeben. Garbage Collection ist nur in VHDL-2019 enthalten, in früheren Versionen von VHDL müssen Sie mit Speicherlecks rechnen, wenn Sie diese Zeile weglassen. Am Ende der for-Schleife schreiben wir bei Bedarf Füllbytes, um die Zeilenlänge auf ein Vielfaches von 4 Bytes zu bringen.

  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 blue pixel
      write(out_file,
        character'val(to_integer(unsigned(row(col_i).blue))));

      -- Write green pixel
      write(out_file,
        character'val(to_integer(unsigned(row(col_i).green))));

      -- Write red pixel
      write(out_file,
        character'val(to_integer(unsigned(row(col_i).red))));

    end loop;

    deallocate(row);

    -- Write padding
    for i in 1 to padding loop
      write(out_file, character'val(0));
    end loop;

  end loop;

Nachdem die Schleife beendet ist, geben wir den Speicherplatz für image frei variabel, wie unten gezeigt. Dann schließen wir die Dateien, indem wir file_close aufrufen auf den Aktengriffen. Dies ist in den meisten Simulatoren nicht unbedingt erforderlich, da die Datei implizit geschlossen wird, wenn das Unterprogramm oder der Prozess beendet wird. Trotzdem ist es nie verkehrt, Dateien zu schließen, wenn Sie damit fertig sind.

  deallocate(image);

  file_close(bmp_file);
  file_close(out_file);

  report "Simulation done. Check ""out.bmp"" image.";
  finish;
end process;

Am Ende des Testbench-Prozesses geben wir eine Nachricht an die ModelSim-Konsole aus, dass die Simulation beendet ist, mit einem Hinweis darauf, wo das Ausgabebild zu finden ist. Der finish Schlüsselwort erfordert VHDL-2008, es ist eine elegante Möglichkeit, den Simulator zu stoppen, nachdem alle Tests abgeschlossen sind.

Das ausgegebene BMP-Bild

Das folgende Bild zeigt, wie die Datei „out.bmp“ nach Abschluss der Testbench aussieht. Die eigentliche Datei, die in diesem Blogbeitrag gezeigt wird, ist ein JPEG, da BMPs nicht zum Einbetten auf Webseiten geeignet sind, aber Sie können Ihre E-Mail-Adresse im obigen Formular hinterlassen, um eine ZIP-Datei mit dem vollständigen Projekt einschließlich der Datei „boeing.bmp“ zu erhalten.

Letzte Bemerkungen

Für die Bildverarbeitung in FPGA wird häufig das YUV-Farbcodierungsschema anstelle von RGB verwendet. In YUV wird die Luma-Komponente (Luminanz) Y von den Farbinformationen getrennt gehalten. Das YUV-Format entspricht eher der menschlichen visuellen Wahrnehmung. Glücklicherweise ist es einfach, zwischen RGB und YUV zu konvertieren.

Das Konvertieren von RGB in CMYK ist etwas komplizierter, da es keine Eins-zu-eins-Pixelformel gibt.

Eine weitere Alternative bei der Verwendung solch exotischer Kodierungsschemata besteht darin, Ihr eigenes Bilddateiformat zu erfinden. Speichern Sie die Pixel-Arrays einfach in einem benutzerdefinierten Dateiformat mit der Endung „.yuv“ oder „.cmyk“. Es ist kein Header erforderlich, wenn Sie wissen, welches Bildformat die Pixel haben werden. Lesen Sie es einfach in Ihrer Testbench nach.

Sie können jederzeit eine Softwarekonvertierung in Ihren Designablauf integrieren. Konvertieren Sie beispielsweise ein PNG-Bild automatisch in das BMP-Format, indem Sie eine Standard-Befehlszeilen-Bildkonvertierungssoftware verwenden, bevor die Simulation beginnt. Lesen Sie es dann in Ihrer Testbench mit VHDL, wie Sie es aus diesem Artikel gelernt haben.


VHDL

  1. Hologramm
  2. C# verwenden
  3. C Dateiverwaltung
  4. Java-Dateiklasse
  5. So initialisieren Sie RAM aus einer Datei mit TEXTIO
  6. Java BufferedReader:Lesen von Dateien in Java mit Beispiel
  7. Python JSON:Codieren (Dumps), Decodieren (Laden) und JSON-Datei lesen
  8. Verilog-Datei-IO-Operationen
  9. C - Header-Dateien
  10. plenoptische Kamera