Multimedia-Entwicklung mit SDL
Bilder anzeigen
SDL kann ohne zusätzliche Bibliotheken nur Bitmapbilder anzeigen. Dies reicht im Normalfall nicht aus. Deshalb weise ich bereits jetzt auf die Standardbibliothek SDL_image hin, die wir auch gleich verwenden werden:
Anmerkung: Bild tux.jpg kann HIER heruntergeladen werden.
#include "sdl_image.h" [...] SDL_Surface *image; [...] image = IMG_Load("tux.jpg"); if (image == NULL) { fprintf(stderr, "Das Bild konnte nicht geladen werden:%s\n", SDL_GetError()); exit(-1); } // kopiere das Bild-Surface auf das display-surface SDL_BlitSurface(image, NULL, display, NULL); // den veraenderten Bereich des display-surface auffrischen SDL_Flip(display); SDL_Delay(3000); // Das Bitmap-Surface löschen SDL_FreeSurface(image); [...]
Die Funktion IMG_Load() wird von sdl_image bereit gestellt. Dies erfordert, dass man SDL_image.h inkludiert und dem Linker ein "-lSDL_image" als Flag mitgibt, wie bei der libsdl oben bereits beschrieben.
Wir deklarieren ein neues Surface mit dem Namen "image". Mittels IMG_Load() weisen wir diesem neuen Surface dann das gewünschte Bild zu. Diese Surface hat nun die Größe der geladenen Grafik.
Da wir meist mehr über die Surfaceformatierung erfahren wollen, wie zum Beispiel die Größe und Farbtiefe, hier die interne Struktur des Surfaces:
typedef struct SDL_Surface { // allgemeine Surface-Informationen Uint32 flags; // Read-only SDL_PixelFormat *format; // Read-only int w, h; // Read-only Uint16 pitch; // Read-only void *pixels; // Read-write int offset; // Private // hardwarespezifisches Surface-Informationen struct private_hwdata *hwdata; // Clipping-Informationen int clip_minx; // Read-only int clip_maxx; // Read-only int clip_miny; // Read-only int clip_maxy; // Read-only // surface-interne Kopierinformationen struct SDL_BlitMap *map; // Private // Liste der surfaces struct map_list *mapped; // Private // Reference-Counter int refcount; // Read-mostly } SDL_Surface;
In der Struktur des Surfaces wird über die Integer-Werte w und h, die Breite und die Höhe gespeichert. Zu Kontrollzwecken wird man daher oft z.B. "image->w" und "image->h" mit ausgeben, um über die zu ändernde Bildgröße informiert zu sein.
Nachdem das Bild nun in sein eigenes Surface geladen wurde, und wir vorerst keine weiteren Veränderungen mehr daran vornehmen wollen, müssen wir es auf das display-surface kopieren. Dies geschieht über SDL_BlitSurface(). BlitSurface nimmt als Parameter:
SDL_BlitSurface(QuellSurface, Quellbereich, ZielSurface, Zielbereich)
Die Parameter Quell- und Zielbereich werden später genauer erklärt, wenn wir die Grafikroutinen intensiver nutzen. Wir gebrauchen SDL_BlitSurface() im Moment so, dass wir als Parameter für die Bereiche einfach 0 übergeben und somit das gesamte Surface kopiert wird.
Als letzten Schritt wollen wir nun das durch das Blitting veränderte display-surface auch zur Anzeige bringen. Die einfachste Möglichkeit ist, dies durch int SDL_Flip(SDL_Surface *display)
zu machen. Hierbei wird (wie schon beim Blit) einfach das gesamte display-surface neu geladen.
Um das Programm speichertechnisch sauber beenden zu lassen, rufen wir für alle Surfaces (außer dem display) die Funktion SDL_FreeSurface() auf, um den allokierten Speicher dafür wieder frei zu geben.