Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 16 SDL
  gp 16.1 Was ist und kann SDL?
  gp 16.2 SDL installieren
  gp 16.3 SDL-Anwendungen erstellen
  gp 16.4 SDL initialisieren und Videomodus einstellen
    gp 16.4.1 Programmbeispiel – SDL initialisieren und Videomodus einstellen
  gp 16.5 Direkt auf den Bildschirm zeichnen
    gp 16.5.1 Programmbeispiel – direkt auf den Bildschirm zeichnen
  gp 16.6 Bitmap laden und anzeigen
    gp 16.6.1 Programmbeispiel – Bitmap laden und anzeigen
  gp 16.7 Ein anderes Grafikformat laden und anzeigen
  gp 16.8 Der rechteckige Bildbereich von SDL
  gp 16.9 Farbenschlüssel, Transparenz und Alpha-Blending
    gp 16.9.1 Alpha-Blending
  gp 16.10 Animation
    gp 16.10.1 Programmbeispiel – Animation
  gp 16.11 Eingabe- und Ereignisverarbeitung
    gp 16.11.1 SDL-Event-Struktur
    gp 16.11.2 Maus-Events
    gp 16.11.3 Programmbeispiel – Maus-Event
    gp 16.11.4 Tastatur-Events
    gp 16.11.5 Programmbeispiel – Tastatur-Events
    gp 16.11.6 Joystick-Events
    gp 16.11.7 Programmbeispiel – Joystick-Events
    gp 16.11.8 Weitere Events
  gp 16.12 Audio
    gp 16.12.1 Programmbeispiel – Audio
  gp 16.13 Ausblick


Rheinwerk Computing

16.8 Der rechteckige Bildbereich von SDL  toptop

Im Abschnitt zuvor wurde die Struktur SDL_Rects schon kurz angesprochen. Zwar handelt es sich hierbei um eine simple Struktur für einen rechteckigen Bereich, wo die Position von links oben und die Größenangabe gespeichert wird, doch ist gerade diese Information eine der wichtigsten in der SDL-Programmierung. Die Struktur SDL_Rect ist wie folgt definiert:

typedef struct {
  Sint16 x, y;
  Uint16 w, h;
} SDL_Rect;

x und y stehen für die linke obere Ecke und w für die Breite, h für die Höhe des rechteckigen Bereichs – der Bildausschnitt, wenn Sie so wollen.

Im Beispiel zuvor wurde beim Anzeigen eines Bildes der komplette Videomodus verändert – was in der Praxis natürlich absolut ineffizient ist. Wenn Sie also ein Surface fester Größe erstellt haben, können Sie somit mit dieser Struktur nur einen bestimmten Bereich im Surface erneuern. Oft will man vielleicht auch nur einen kleinen Teilbereich erneuern – was sich gerade aus Performancegründen auch empfiehlt. Und dabei muss nicht immer das komplette Surface neu kopiert werden (was gerade bei größeren Bilddateien auf Dauer negativ auffällt).

Um Ihnen zu demonstrieren, worum es sich bei einem Bildbereich handelt, soll das Beispiel vom Abschnitt zuvor ein wenig umgeschrieben werden. Die Bilder, die zuvor auf dem veränderbaren Surface dargestellt werden, sollen nun auf einem Surface fester Größe wiedergegeben werden. Außerdem sollen die Bilder zur Demonstration um 50 x 50 Pixel vom rechten oberen Bereich eingerückt werden. Dies erledigen Sie, indem Sie den rechteckigen Bereich des Haupt-Surfaces mit der Struktur SDL_Rect verändern:

   SDL_Rect ziel;
   ...
   ziel.x = 50;
   ziel.y = 50;
   ziel.w = bild->w;
   ziel.h = bild->h;

Jetzt benötigen Sie noch einen zweiten rechteckigen Bereich für das Surface des Bildes. Dieses Surface stellt ja den Quellbereich da, den Sie anschließend mit der Funktion SDL_BlitSurface() in den rechteckigen Zielbereich ziel kopieren (die Funktion wurde bereits behandelt). Den Zielbereich ziel verwenden Sie nun, um wirklich auch nur den rechteckigen Bereich des Bildes zu erneuern, der neu auf dem Bildschirm erscheint. Häufig werden hierzu auch wiederum nur Bildausschnitte eines Bildbereichs benötigt. Diese Angaben müssen Sie allerdings dann bei dem rechteckigen Quellbereich machen, der folgendermaßen aussehen kann:

  SDL_Rect quelle;
  ...
  for (i = 640; i--;) {
     quelle.x = i + 50;
     quelle.y = 0;
     quelle.w = bild->w / 2 + 50;
     quelle.h = bild->h;
     SDL_BlitSurface (bild, &quelle, screen, &ziel);
     /* den veränderten Bildschirmbereich auffrischen */
     SDL_UpdateRects (screen, 1, &ziel);
  }

Sie können damit anschließend in der Praxis gerne herumexperimentieren. Würden Sie jetzt das Neuzeichnen mit einem Funktionsaufruf von

SDL_UpdateRect(screen,0,0,0,0);

machen, würden Sie wieder das komplette Surface neu zeichnen. Zwar wäre es auch möglich, wirklich nur den aktuellen Bildbereich neu zu zeichnen, der nötig ist, allerdings kann dies recht schnell fehleranfällig werden. Für solch einen Fall eignet sich hervorragend die Funktion:

 void SDL_UpdateRects( SDL_Surface *display,
                       int numrects, SDL_Rect *rects );

Mit SDL_UpdateRects() können Sie einfach und komfortabel den rechteckigen Bereich rects im Ziel-Surface display angeben, der neu gezeichnet werden soll. Der zweite Parameter numrects zeigt es auch schon an, dass es möglich ist, mit dieser Funktion gleich mehrere Rechtecke auf einmal zu erneuern. Hierfür müssten Sie allerdings ein Array vom Typ SDL_Rects als dritten Parameter übergeben.

Dass wirklich nur ein rechteckiger Bereich gezeichnet wird, zeigt Ihnen das gleich folgende Beispiel, wenn das nächste Bild (oder der Ausschnitt) davon über das vorherige Bild geschoben wird, ohne dass das vorherige Bild verschwindet. Das Beispiel lädt geradezu ein, mit den Parametern zu spielen. Beispielsweise wird ein Bild von oben eingeschoben und eines von links – hierfür können Sie ja die Funktion SDL_UpdateRects() mit einem SDL_Rect-Array verwenden.

/* sdl5.c */
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd. h.>
static void display_bmp (const char *datei, SDL_Surface * screen,
                         int x, int y) {
  SDL_Surface *bild;
  SDL_Rect ziel, quelle;
  int i;
  /* lädt die BMP-Datei in ein Surface */
  bild = IMG_Load (datei);
  if (bild == NULL) {
    fprintf (stderr, "'%s' konnte nicht geladen werden: %s\n",
       datei, SDL_GetError ());
    return;
  }
  /* auf den Bildschirm kopieren                     */
  /* die Surfaces sollten hier nicht gelockt sein.   */
  /* x,y = linke obere Ecke; w, h = Breite und Höhe  */
  ziel.x = 50;
  ziel.y = 50;
  ziel.w = bild->w;
  ziel.h = bild->h;
  for (i = 640; i--;) {
    quelle.x = i + 50;
    quelle.y = 0;
    quelle.w = bild->w / 2 + 50;
    quelle.h = bild->h;
    SDL_BlitSurface (bild, &quelle, screen, &ziel);
    /* den veränderten Bildschirmbereich auffrischen */
    SDL_UpdateRects (screen, 1, &ziel);
  }
  SDL_FreeSurface (bild);
}
int main (int argc, char **argv) {
  SDL_Surface *screen;
  int i;
  if (argc == 1) {
    printf ("Bitte mindestens eine gültige Grafikdatei "
            " angeben!\n");
    return EXIT_FAILURE;
  }
  /* SDLs Videosystem initialisieren und auf Fehler prüfen */
  if (SDL_Init (SDL_INIT_VIDEO) != 0) {
    printf ("Konnte SDL nicht initialisieren: %s\n",
       SDL_GetError ());
    return EXIT_FAILURE;
  }
  /* Wenn die Anwendung beendet wird,          */
  /* wird die Funktion SDL_Quit() ausgeführt   */
  atexit (SDL_Quit);
  /* Videomodus mit 640 x 480 Pixel, Hi-Color (16 Bit) */
  /* einrichten Oberfläche (Surface) Standardmäßig in */
  /* den Hauptspeicher (SDL_SWSURFACE) legen          */
  screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE);
  if (screen == NULL) {
    printf ("Videomodus konnte nicht eingerichtet werden: "
            " %s\n", SDL_GetError ());
    return EXIT_FAILURE;
  }
  /* Slideshow starten                                       */
  /* Zeigt alle BMP-Bilddateien an, die in der Kommandozeile */
  /* mit angegeben wurden                                     */
  for (i = 1; argv[i] != NULL; i++) {
    display_bmp (argv[i], screen, 0, 0);
    SDL_Delay (1000);  
  }
  printf ("Erfolgreich beendet!\n");
  return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc `sdl-config --libs` `sdl-config --cflags` -o \
  sdl5 sdl5.c -lSDL_image
$ ./sdl5 john2.bmp john.bmp john2.bmp john.bmp

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 16.3    Einzelne rechteckige Bildbereiche neu zeichnen


 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern