Bilder als Ressourcen
Inhaltsverzeichnis
Vorwort
Eins vorneweg: Da ich noch OpenGL-Frischling bin, sollten die in diesem Artikel beschriebenen Methoden zwar funktionieren, jedoch bin ich fast der Überzeugung, dass sie Speicher- sowie Performancetechnisch eher miserabel sind...
Einleitung
Man kann Bilder (und auch jeglichen anderen Daten) beispielsweise in Ressourcen-Dateien packen,
um die .exe möglichst klein zu halten.
Oder aber man freut sich, wenn man immer alle Grafiken in einer Datei zusammen hat.
Oder man verwendet Ressourcen-Dateien, damit "net jeder Wald und Wiesendepp mit Paint die Grafiken verunstalten kann" (Zitat Flash)
Warum auch immer man sich für Ressourcen-Dateien entscheiden sollte, die Herangehensweise ist die selbe - nämlich folgende:
.RES Datei Erstellen...
Als erstes nehmen wir alle Grafiken, die wir brauchen, und packen sie in eine .res Datei.
"packen" weckt hier möglicherweise falsche Hoffnungen, denn die Daten werden dadurch nicht komprimiert, sie kommen bloß alle zusammen in eine Datei.
Um eine solche .res Datei zu erschaffen gibt es mehrere Wege - hier sind zwei:
einfach und schnell
Man benutzt das Programm "PE Resource Explorer", mit welchem man sich recht bequem seine Resourcen zusammen klicken kann. (Download: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm)
selber tippen
Die andere Möglichkeit ist etwas mehr Arbeit: Also schnappst du dir Notepad oder sonst irgendeinen Editor und erstellst eine Datei mit folgendem Format:
<Ressourcenbezeichner> <Resourcentyp> <Pfad zur Datei>
beispielsweise:
myCharTex BITMAP char.tga
- Ressourcenbezeichner: ist der Name, den du der Ressource gibst. Statt einem String kannst du auch ne Zahl hinschreiben, also:
- 10 BITMAP holla.bmp
- Muss man selber wissen, ob man lieber mit Strings oder Integers als Bezeichner arbeitet, hat bestimmt beides Vorzüge...
- Ressourcentyp: Es gibt einige vordefinierte Typen (für Bitmaps, Jpgs, Cursor, Icon, usw)
- Für alle Sachen, die nicht explizit nen eigenen Typ haben gibt es RCDATA
- Das wär dann wohl allgemeine Datenvielfalt, oder so...
- Pfad zur Datei: ist selbsterklärend denke ich.
- Kann sein, dass man Gänsefüsschen setzen muss, keine Ahnung - testen!
Jetzt hast du im Editor zeilenweise deine Ressourcen angegeben und speicherst das Werk erstmal als Datei mit der Endung ".rc" ab.
Dann gibt es in deinem Delphi Verzeichnis einen Ordner "bin" und in selbigem eine Datei brcc32.exe - die brauchen wir jetzt.
Die .rc Datei enthält ja nur die Dateinamen zu den Ressourcen die du haben willst. brcc32.exe nimmt sich diese Datei und packt die darin angegebenen Ressourcen in eine .res Datei.
Dazu ruft man die brcc32 in der Kommandozeile auf und übergibt als Parameter den Pfad zur .rc Datei
Ipp Zipp Zapp, fertig ist die .res Datei
Dieser zweite Weg ist zwar unter Umständen mehr Arbeit, aber dafür hat man dann auch n bisschen Hintergrundwissen abbekommen - kann ja nicht schaden.
...und einbinden
Soweit so gut, wir haben die Resourcen alle in einer .res Datei und binden diese mit {$R lemon.RES} in unser Programm ein...
HA! Wenn man die .res Datei in das Hauptprojekt eingebunden hätte, wäre sie beim compilieren mit in die .exe hineinkompiliert worden.
Weil wir das aber nicht wollen, gehen wir her und erstellen in Delphi ein neues DLL Projekt.
Den vorgeschriebenen Quelltext ersetzen wir mit:
library lemon; {$R lemon.RES} begin end.
wobei der Name der Library und "lemon.RES" natürlich auf eure Bedürfnisse angepasst werden sollte.
Wunderbar, jetzt speichern wir das Projekt, compilieren es und der ein oder andere kann auch "Hosianna" rufen, denn jetzt haben wir eine wunderschöne .dll Datei, die all unsere Resourcen enthält. Und ich denke, jeder gewöhnliche Wald und Wiesen Depp, wird sich denken "Möh? DLL - Wasn datt da? Kann man das essen?? Lass ich mal lieber in Ruhe"
Hehe, aber wir sind noch nicht am Ziel... wir müssen die Daten ja auch wieder aus der DLL rausbekommen.
Ressourcen laden
Zurück in der Hauptanwendung gehen wir folgendermaßen vor:
Erstmal brauchen wir eine Variable vom Typen Papst ääh, Cardinal.
Der weisen wir mittels
var h: cardinal; h := LoadLibrary('lemon.dll');
die eben erstelle DLL Datei zu.
Wenn man jetzt in LoadFromRessource oder ähnlichen Funktionen als Parameter eine Instance angeben sollst, ist das unsere Cardinal Variable, die ja auf die DLL zeigt.
Bei der glBitmap.pas laden wir allerdings immer aus Streams - und zwar so:
var myStream: TResourceStream var h: Cardinal; var foo: TglBitmap2D; // DLL Laden h := LoadLibrary('lemon.dll'); // Texturklasse erstellen foo := TglBitmap2D.Create; // Stream auf eine Resource erstellen myStream := TResourceStream.CreateFromID(h, 10, RT_RCDATA); try // Bild aus Stream laden foo.LoadFromStream(myStream); finally // Stream in jedem Falle wieder frei geben myStream.Free; end; // OpenGL Textur erstellen foo.GenTexture; // DLL Wieder entladen wenn sie nicht mehr gebraucht wird FreeLibrary(h);
damit würden wir aus der Datei lemon.dll eine RCDATA Resource mit dem Bezeichner 10 laden.
Wenn man den Ressourcen String-Namen gegeben hat, benutzt man "Create" statt "CreateFromId" und gibt den String an.
Nachwort
Sohohohoho, ich hoffe, ich habe alles Erwähneswerte erwähnt und wenn es jemandem hilft, dann bin ich mächtig stolz, auch mal ne Antwort gegeben zu haben, statt immer nur zu Fragen.
Abgesehen davon hoffe ich, dass ich an dieser Stelle Lossy eX für Geduld und Wissen danken darf :)
Ciao