ビデオはおそらく SDL が使われる最も一般的な部分でしょう。 そのため、最も完成されたサブシステムを持っています。 基本をデモンストレーションするためのいくつかの例を出します。
これはほとんどすべての SDL プログラムがどうにかして しなければいけないことでしょう。
Example 2-1. ビデオ表示の初期化
SDL_Surface *screen;
/* SDL ライブラリを初期化 */
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr,
"SDL が初期化できませんでした: %s\n", SDL_GetError());
exit(1);
}
/* 終了時の後片付け */
atexit(SDL_Quit);
/*
* ソフトウェアサーフェスを要求し、
* 画面を 640x480 パレットモードで初期化
*/
screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "640x480x8 のビデオモードに設定できませんでした: %s\n",
SDL_GetError());
exit(1);
}指定したいピクセル深度があるけれども、他でもよい場合は、 以下のように SDL_ANYFORMAT をつけて SDL_SetVideoMode を使います。 要求されるものに最も近い、ハードウェアがサポートするビデオモードを 見つけるために SDL_VideoModeOK() を使うこともできます。
Example 2-2. 最良のビデオモードの初期化
/* 8-bit を指定したいが、どんな深度でも可能 */
screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT);
if ( screen == NULL ) {
fprintf(stderr, "640x480x8 のビデオモードに設定できませんでした: %s\n",
SDL_GetError());
exit(1);
}
printf("640x480 at %d bpp のモードで 640x480 に設定しました\n",
screen->format->BitsPerPixel);ひとたび SDL が初期化されてビデオモードがセットされたら、 次に挙げる関数は指定された引数の BMP ファイルをロードして表示します。
Example 2-3. BMP ファイルのロードと表示
void display_bmp(char *file_name)
{
SDL_Surface *image;
/* BMP ファイルをサーフェスにロードする */
image = SDL_LoadBMP(file_name);
if (image == NULL) {
fprintf(stderr, "%s: %s がロードできませんでした\n", file_name, SDL_GetError());
return;
}
/*
* パレット画面モードはデフォルトパレットを持つ(標準の 8*8*4 色立体)が、
* 画像もパレット表現ならば、より良く色を合わせるため
* そのパレットを使うことができる
*/
if (image->format->palette && screen->format->palette) {
SDL_SetColors(screen, image->format->palette->colors, 0,
image->format->palette->ncolors);
}
/* Blit onto the screen surface */
if(SDL_BlitSurface(image, NULL, screen, NULL) < 0)
fprintf(stderr, "BlitSurface のエラー: %s\n", SDL_GetError());
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
/* 確保した BMP サーフェスを解放 */
SDL_FreeSurface(image);
}以下の 2 つの関数はサーフェスの 1 ピクセルを取得/書込するために使われます。 それらは SDL によって現在サポートされているどんなピクセル深度においても動くよう 注意深く書き込まれます。
ピクセル値とその赤・緑・青チャンネルの値とを変換するためには、 SDL_GetRGB() と SDL_MapRGB() を使います。
Example 2-4. getpixel()
/*
* (x, y) におけるピクセルを返す。
* 注意: これを呼ぶ前にサーフェスがロックされている必要がある!
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* この p は取得したいピクセルを指すアドレス */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0; /* 起こるはずがないが、ワーニングを回避 */
}
}Example 2-5. putpixel()
/*
* (x, y) におけるピクセルに指定された値をセットする。
* 注意: これを呼ぶ前にサーフェスがロックされている必要がある!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* この p は取得したいピクセルを指すアドレス */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}以下のコードは、画面の中央に黄色いピクセルを書込むために、 上記の putpixel() 関数を使っています。
Example 2-6. putpixel() を使う
/* Code to set a yellow pixel at the center of the screen */
int x, y;
Uint32 yellow;
/* 黄色をこの画面に写像する (R=0xff, G=0xFF, B=0x00)
注意: 画面がパレットで表現されているなら、まずパレットをセットする必要がある
*/
yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
x = screen->w / 2;
y = screen->h / 2;
/* ピクセルへの直接アクセスのため画面をロック */
if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
fprintf(stderr, "画面のロックができません: %s\n", SDL_GetError());
return;
}
}
putpixel(screen, x, y, yellow);
if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
/* 画面の書き換えた部分だけを更新 */
SDL_UpdateRect(screen, x, y, 1, 1);
return;