====== Bitmaps ====== Attraktive Bilder, mit Lichteffekten, Texturen und vielen Details, lassen sich mit vertretbarem Aufwand (falls man nicht gerade einen [[http://de.wikipedia.org/wiki/Bildsynthese|3D Renderer]] zur Hand hat) in der Regel nur mit sogenannter [[http://de.wikipedia.org/wiki/Rastergrafik|Rastergrafik (Pixelgrafik)]] darstellen. Das Gleiche gilt für Fotografien. Auch diese werden als Rastergrafik gespeichert und dargestellt. >>>{{::beispielbitmap.jpg?direct&200|}} Was die Rastergrafik betrifft, ähneln Bitmaps durchaus den Icons. Der wesentliche Unterschied besteht in der [[http://de.wikipedia.org/wiki/Farbtiefe_(Computergrafik)|Farbtiefe]] und der Pixelanzahl (Bildgröße). Icons verwendetet lediglich eine Auswahl von Farben aus einer Palette, während Bitmaps die Farbe jedes einzelnen Bildpunktes im [[http://de.wikipedia.org/wiki/RGB-Farbraum|RGB-Farbmodell]] abbildet. Bitmaps verbrauchen somit wesentlich mehr Speicher. ====== Aufgabe ====== Es ist ein Bitmap mit einer Größe von 240x320 Pixeln auf dem Display darzustellen. ====== Vorbereitung ====== Falls Sie nicht in der Vorgehensmodell-Ebene sind, navigieren Sie diese bitte an (nach oben). Falls das Projekt nicht mehr geöffnet ist, öffnen sie das SiSy UML-Projekt wieder. Legen Sie ein neues Klassendiagramm an und wählen Sie die Sprache //ARM C++//. Beachten Sie die Einstellungen für die Zielplattform STM32F4-Discovery. Beim Öffnen des Diagramms (rechte Maustaste, nach unten) laden Sie die Diagrammvorlage für eine //ARM C++ Applikation mit Grafikdisplay ohne µGL//. >>><flashplayer width="400" height="325">file=http://youtu.be/Bgj90aciLiI</flashplayer> Selektieren Sie die Operation //onStart// der Klasse Application. >>>{{:ggohnegl.png?direct&750|}} Ersetzen Sie möglicherweise vorhandenen Beispielquelltext durch folgenden Code. >>>**onStart()** >>><code cpp> display.clearScreen(); </code> Erstellen und übertragen Sie die Anwendung auf den Mikrocontroller. ====== Grundlagen zu Bitmaps ====== Bitmaps können prinzipiell auch von einem Speichermedium gelesen werden. Dazu benötigt man ein [[http://sisy.de/index.php?id=6&_cmd=showPage&_para=searchLibList&searchTxtLib=FAT|Dateisystem]] und einen [[https://www.google.de/search?q=jpeg+decoder+c+source&oq=jpg+decoder+c&aqs=chrome.2.69i57j0l5.15681j0j8&sourceid=chrome&espv=210&es_sm=93&ie=UTF-8|Decoder]] für das entsprechende Format der Datei ([[http://de.wikipedia.org/wiki/Windows_Bitmap|BMP]], [[http://de.wikipedia.org/wiki/JPG|JPG]], [[http://de.wikipedia.org/wiki/Portable_Network_Graphics|PNG]], ...). Steht kein Speichermedium, wie zum Beispiel eine SD-Karte, zur Verfügung, können die Bitmaps ähnlich wie die Icons im Programm selbst //abgelegt// werden. Die folgenden Ausführungen beziehen sich darauf, dass die Bitmaps im Flash abgelegt und in C++ codiert werden. Als Erstes soll der µGL-Bitmap-Header besprochen werden. Diese Struktur wird jedem Bitmap vorangestellt. Das Strukturelement //Typ// enthält ein //'b'// für die Kennzeichnung eines Bitmaps. >>><code cpp> struct BitmapHeader{ char type; // ='b' ... Bitmap uint8_t framesCount; uint16_t width; uint16_t height; const color_t** frameList; }; </code> Ein Bitmap-Header kann auf eine oder mehrere Bitmaps gleicher Größe verweisen. Dazu wird die Anzahl und die Größe der Frames angegeben. Als letztes Element folgt ein Zeiger auf die Bitmap-Daten des ersten Frames. Sollten mehrere Frames vorhanden sein, folgt eine entsprechende Anzahl von Verweisen. Ein einfaches Bitmap besitzt ein Frame. >>>**{{Bitmapdaten.zip|Bitmapdaten}}:** >>><code cpp> const color_t _bmp_data_demoPicture[] = { 0xFF30, 0xFFDF, ... 0xDD30, 0xFFDF }; </code> >>>**der dazugehörige BitmapHader:** >>><code cpp> BitmapHeader _bmp_demoPicture = { 'b', 1, 240, 320 , _bmp_frames_demoPicture }; </code> Das RGB Farbmodell wird in den meisten Fällen mit einer [[http://de.wikipedia.org/wiki/Farbtiefe_(Computergrafik)|Farbtiefe]] von 24 Bit abgebildet. Das entspricht 8 Bit je Farbe ( RGB-8-8-8, [[http://de.wikipedia.org/wiki/True_Color|True Color]], 16.777.216 Farben ). Sind die Ressourcen des Systems knapp, kann die Farbtiefe reduziert werden ohne dass es dem menschlichen Auge groß auffällt. Die in diesem Tutorial verwendeten Boards verfügen über eine maximale Farbtiefe von 16 Bit ( RGB-5-6-5, [[http://de.wikipedia.org/wiki/High_Color|Heigh Color]], 65.536 Farben). Die nächstkleinere akzeptable Farbtiefe ist Real Color mit 15 Bit und 32.768 Farben. Daraus ergibt sich ein RGB-5-5-5 und es wird in einem 16-Bit-Farbword ein Bit frei ;-) >>> [ R R R R R G G G | G G x B B B B B ] 16 ^ 0 | Die Bitstelle 5 kennzeichnet eine Metainformation 0 = RGB-5-5-5 1 = Metainformation = 0b0000000000100000 = 0x0020 Die Metainformationen sollen zusätzlich zu normalen Farbinformationen, zum Beispiel Transparenz, Hintergrund- oder Vordergrundfarben und was besonders interessant ist Komprimierungsinformationen, codieren. Im Folgenden die entsprechenden Deklarationen: >>><code cpp> typedef unsigned short color_t; // = uint16_t // RGB to 5-5(6)-5 #define RGB(r,g,b) ( (((r)&0xF8)<<8) | (((g)&0xF8)<<3) | ((b)>>3) ) #define ColorTransparent 0x0020 #define ColorForeground 0x0021 #define ColorBackground 0x0022 #define ColorHalfTransparent 0x0023 #define ColorInvalid 0x002F #define ColorCompressed 0x0030 ... </code> Sehen wir uns den Codeabschnitt //0xFF30, 0xFFDF,// aus den {{Bitmapdaten.zip|Bitmapdaten}} näher an: * //0xFF30//, 16 Bit Wert aus den Bitmapdaten * das interessante Bit 5 ist gesetzt * zusätzlich Bit 4 das ergibt die Maske: * //0x0030// = ColorCompressed * //0xFF00// = das High-Byte enthält die Anzahl der Bildpunkte * das bedeutet die folgende Farbe wiederholt sich 255 mal * //0xFFDF//, der folgende 16 Bit Wert aus den Bitmapdaten * entspricht 0b1111111111011111 * das Bit 5 ist nicht gesetzt, es ist also eine Farbe * R = 0b11111 , G = 0b11111, B = 0b11111 * das entspricht der Farbe Weis, im Code als Makro RGB(255,255,255) Die Codierung von Farben wird vom Anwendungsentwickler im Quelltext als 24 Bit Farbe notiert. Das RGB-Makro konvertiert die Farbangabe in die vom Displaytreiber verwendete 16Bit Farbtiefe. Ein Bitmap mit 240 x 320 Pixeln codiert kein Anwednungsentwickler von //Hand//. Das gäbe eine ordentliche Sehnenscheidenentzündung. Dafür bedient man sich Werkzeugen wie dem [[funktionen_des_bitmap-designer-tool|Icon-Desinger und Bitmap-Konverter]]. Aus diesem Werkzeug wurde auch der Inhalt für die Datei {{Bitmapdaten.zip|Bitmapdaten.h}} generiert. ====== Entwurf der Bitmap-Anwendung ====== Die Programmschritte zum darstellen eines Bitmaps sind denkbar einfach: - Bildschirm löschen, Funktion //[[http://www.myugl.de/_referenz/v003/Lcd_SSD1289.htm#79_Details|clearScreen]]// - Bitmap darstellen, Funktion //[[http://www.myugl.de/_referenz/v003/Lcd_SSD1289.htm#93_Details|drawBitmap]]// Da das Bitmap recht groß ist, soll es nicht innerhalb einer Operation oder Klasse abgelegt werden, sondern eine eigene Datei bekommen. Dazu benutzt man in der UML das Artefakt. >>>{{::artefakt.png?direct&100|}} Die eigentlichen Bitmapdaten lassen wir uns entweder vom [[http://myugl.de/_wiki/doku.php?id=funktionen_des_bitmap-designer-tool|Icon- und Bitmap-Konverter]] generieren oder nehmen die vorbereiteten {{Bitmapdaten.zip|Bitmapdaten}} zur Hand. ====== Realisierung der Bitmap-Anwendung ====== Sie haben in der Vorbereitung ein Grundgerüst für eine einfache Grafikanwendung geladen und den Quellcode der Operation //onStart// mit einem //display.clearScreen()// erstellt. >>>{{:ggohnegl.png?direct&750|}} Ziehen Sie aus der Objektbibliothek ein Element vom Typ //Artefakt// in das Klassendiagramm. Geben Sie dem Artefakt den Namen //Bitmapdaten//. Das Artefakt soll generiert und in die Anwendung eingebunden werden. Der Dateiname soll //bitmapdaten.h// lauten. Vergleichen Sie die Einstellungen mit dem folgenden Dialog: >>>{{::artefaktdlg.png?direct&300|}} Verbinden Sie das Artefakt mit der Klasse //Application// als //Abhängigkeit// mit dem Stereotyp //<<include>>//. >>>{{::bitmapkd.png?direct&750|}} Kopieren Sie den Inhalt der {{Bitmapdaten.zip|Bitmapdaten}} in das Artefakt. >>>{{::bitmapdatencopy.png?direct&700|}} Ergänzen Sie den Quellcode der Operation //onStart// wie folgt: >>>**onStart:** >>><code cpp> // Bildschirm aufräumen display.clearScreen(); // Bitmap darstellen display.drawBitmap( 0, 0, bmpDemoPicture ); </code> Erstellen und übertragen Sie das Programm auf den Mikrocontroller. Vergleichen Sie die Anzeige mit dem Quellcode. ====== Videozusammenfassung ====== >>><flashplayer width="600" height="475" position="0">file=http://youtu.be/t1N5-klEpyc</flashplayer> >>>[[http://youtu.be/t1N5-klEpyc|besser auf youTube]] ====== Nächstes Thema ====== * [[Schriften|Schriftarten und Schriftstile]] * [[weitere_funktionen_des_grafikdisplays|zum übergeordneten Abschnitt]] * [[start|zur Gesamtübersicht]]