Da es sich hier um eine Bibliothek handelt und die Bilder eine ihrer Schnittstellen zu den Klienten darstellen, ist die Definition einer eigenen Bildklasse nötig. Es kann vom Klienten nicht erwartet werden, daß er mit ``platten'' Bildpuffern arbeitet, deren internes Format wie Dimensionen, Farbraum und Kodierung nicht ersichtlich ist. An solch schlecht dokumentierten aber komplexen Schnittstellen scheitert oft der Einsatz einer Bibliothek. Außerdem widerspräche ein solches Vorgehen allen Geboten der Datenkapselung, was schnell zu undefiniertem, schwer zu debugenden Verhalten führen kann.
Diese Bildklasse sollte also ausreichend komfortabel bei der Erzeugung und Verwendung sein, einen Zugriff auf einzelne Pixel über ihre Bild-Koordinaten ermöglichen und trotzdem an dieser wichtigen und die Performance des gesamten Systems wesentlich beeinflussenden Stelle keinen Overhead produzieren.
Obwohl die Bibliothek intern mit RGB-Werten arbeitet, sollte sich die Bildklasse doch auch einfach auf andere Farbräume anpassen lassen.
Die gefundene Lösung verwendet eine Kombination aus Templates und Vererbung, um die eben genannten Kriterien zu erfüllen.
Basis der Bildklasse stellt eine Templateklasse (CMapWrapper)
dar, die
allgemein Matrizen verschiedener Größe kapselt. Da die Größe der Matrizen
erst zur Laufzeit bekannt wird und sich ändern kann, kommt die Verwendung
eines zweidimensionalen C/C++ Arrays nicht in Frage. Hier muß zumindest eine
Dimension zur Übersetzung bekannt sein. Üblicherweise wird daher ein flaches
Array verwendet, in dem die Zeilen hintereinander abgespeichert werden.
Die Zugriffsstelle für die Koordinaten ist dann durch den Term
gegeben, wobei
die Anzahl der Spalten pro Zeile angibt. In solch
einem Format werden die Daten auch vom video4linux Interface und im
Grafikspeicher bereitgehalten. Soll mit Hilfe der Koordinaten auf einen
Punkt
in dem Feld zugegriffen werden, muß die Stelle also erst berechnet werden. Eine
andere und schnellere Methode ist es, ein Array von Zeilenzeigern anzulegen,
die auf den Anfang einer jeden Zeile verweisen (Abbildung 2.5).
Dieses Array verwendet
zusätzlichen Platz in Abhängigkeit der Anzahl der Zeilen und muß bei einer
Größenänderung neu aufgebaut werden. Das Array gewährleistet aber einen
effizienteren
Zugriff auf jedes einzelne Pixel. Da Pixelzugriffe wesentlich häufiger als
Größenänderungen auftreten, wird hier die Methode der Zeilenzeiger verwendet.
![]() |
Die Behandlung des Speichers und die Verwaltung der zugehörigen Zeilenzeiger wird in einer inneren Pufferklasse gekapselt. Ein CMapWrapper besitzt einen solchen Puffer und leitet Anfragen an ihn weiter. CMapWrapper verhalten sich bei der Konstruktion, Destruktion und Zuweisung wie sogenannte ``Smart Pointer''. Das heißt, daß verschiedene Objekte der Klasse CMapWrapper denselben Speicher, bzw. dieselbe Instanz der inneren Pufferklasse referenzieren können. Bei der Dekonstruktion wird der Puffer nur freigegeben, wenn er von niemandem mehr verwendet wird. Eine Instanz dieser Klasse kann damit als ``Handle'' eines Bildes im Arbeitsspeicher aufgefaßt werden.
Obwohl von dieser Templateklasse geerbt werden kann, sind alle Zugriffsfunktionen nicht als virtual deklariert. Dies geschah aus Effizienzgründen, um sie inline definieren zu können. Sie sollten daher von einer erbenden Klasse nicht überschrieben werden.
Von diesem allgemeinen Template zur Behandlung von Matrizen wird nun die eigentliche Bildklasse abgeleitet. Dabei wird das Template mit den verwendeten RGB-Werten instanziert.
Außerdem gibt es eine weitere von CRGBMap abstammende Klasse CPPM, die ein RGB-Bild mit Stream Operatoren versieht, die das Ausgeben und Lesen der Bilder im PPM Format ermöglichen. PPM steht für ``Portable Pixmap'' und ist teil der ``Portable Bitmap Utilities''. Das PPM Format steht architekturübergreifend zur Verfügung und bietet unter anderem die Ablage der Bildinformationen als leicht weiterzuverarbeitende ASCII Datei. Das Format wird ausführlich z.B. von Vornberger [21] beschrieben.