第二章 图像和视频
SDL Vidow显示
初始化SDL Video显示
视频是最常用的部分,也是SDL最完整的子系统。下面的初始化过程是每个SDL程序都要做的,即使可能有些不同。
例2-1 初始化视频
SDL_Surface *screen;
/*
Initialize the SDL library */
if(
SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr,
"Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
/* Clean
up on exit */
atexit(SDL_Quit);
/*
* Initialize the display in a 640x480 8-bit palettized mode,
* requesting a software surface
*/
screen =
SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
if (
screen == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
exit(1);
}
初始化最佳视频模式
如果你希望某种色深(颜色数)但如果用户的显示器不支持也可以接受其他色深,使用加SDL_ANYFORMAT参数的SDL_SetVideoMode。您还可以用SDL_VideoModeOK来找到与请求模式最接近的模式。
例2-2 初始化最佳视频模式
/* Have a
preference for 8-bit, but accept any depth */
screen =
SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE|SDL_ANYFORMAT);
if (
screen == NULL ) {
fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n",
SDL_GetError());
exit(1);
}
printf("Set 640x480 at %d bits-per-pixel mode\n",
screen->format->BitsPerPixel);
读取并显示BMP文件
当SDL已经初始化,视频模式已经选择,下面的函数将读取并显示指定的BMP文件。
例2-3 读取并显示BMP文件
void display_bmp(char *file_name)
{
SDL_Surface *image;
/* Load
the BMP file into a surface */
image =
SDL_LoadBMP(file_name);
if (image
== NULL) {
fprintf(stderr, "Couldn't load %s: %s\n", file_name,
SDL_GetError());
return;
}
/*
* Palettized screen modes will have a default palette (a
standard
* 8*8*4 colour cube), but if the image is palettized as well we
can
* use that palette for a nicer colour matching
*/
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 error: %s\n", SDL_GetError());
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
/* Free
the allocated BMP surface */
SDL_FreeSurface(image);
}
直接在显示上绘图
下面两个函数实现在图像平面的像素读写。它们被细心设计成可以用于所有色深。记住在使用前要先锁定图像平面,之后要解锁。
在像素值和其红、绿、蓝值间转换,使用SDL_GetRGB()和SDL_MapRGB()。
例2-4 getpixel()
/*
* Return the pixel value at (x, y)
* NOTE: The surface must be locked before
calling this!
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp =
surface->format->BytesPerPixel;
/* Here p
is the address to the pixel we want to retrieve */
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;
/* shouldn't happen, but avoids warnings */
}
}
例2-5 putpixel()
/*
* Set the pixel at (x, y) to the given
value
* NOTE: The surface must be locked before
calling this!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32
pixel)
{
int bpp =
surface->format->BytesPerPixel;
/* Here p
is the address to the pixel we want to set */
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;
}
}
例2-6 使用上面的putpixel()在屏幕中心画一个黄点
/* Code
to set a yellow pixel at the center of the screen */
int x,
y;
Uint32
yellow;
/* Map
the color yellow to this display (R=0xff, G=0xFF, B=0x00)
Note: If the display is palettized, you must set
the palette first.
*/
yellow =
SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
x =
screen->w / 2;
y =
screen->h / 2;
/* Lock
the screen for direct access to the pixels */
if (
SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
putpixel(screen, x, y, yellow);
if (
SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}
/* Update
just the part of the display that we've changed */
SDL_UpdateRect(screen, x, y, 1, 1);
return;