Surface是平面的含意,在SDL中,所有绘制在视频输出都是通过SDL_Sur对face对象来输出。一个图像,一段文字,一个视频都需要转换成 SDL_Surface对象来操作,它们可以平铺,堆叠。他们所有数据最终要在一个叠加在表示screen 的SDL_Surface的对象中输出显示。
TAG:
SDL
Andrew Huang bluedrum@163.com
Pixel 概念。
数字屏幕是一个二维可显示的像素空间,即一个一个点形成的。如果是黑白色,只需要0,1即可表示。但如果这个点有表达多种颜色。
SDL_Surface 概念
Surface是平面的含意,在SDL中,所有绘制在视频输出都是通过SDL_Sur对face对象来输出。一个图像,一段文字,一个视频都需要转换成SDL_Surface对象来操作,它们可以平铺,堆叠。他们所有数据最终要在一个叠加在表示screen 的SDL_Surface的对象中输出显示。
因此SDL_Surface本质是一个矩形的像素内存,它需要通过专门的绘点函数来输出到不同设备上。
其中SDL_Surface 的坐标系是左上角是原点,向下向左递增.
SDL_Surface的高,宽值保存在结构的w,h成员。(SDL_Surface.w,SDL_Surface.h);
一.屏幕Surface的操作
------------------------------------------------------------------------
一个带图形显示的的SDL程序(基本上所有都带),首先要初始化一个屏幕Surface.其余所有输出到屏幕的Surface数据都要填充到屏幕Surface上。
1.1 初始化屏幕
采用 SDL_SetVideoMode()来初始化屏幕。这个屏幕是特指SDL绘制的窗口,并不是指整个屏幕。
SDL_Surface* SDL_SetVideoMode(int width, int height, int bitsperpixel, Uint32 flags);
width,height是输出高和宽,bitsperpixel 就是指bpp.即每点像素数,取值 8,16,32,值越大,说明屏幕表现力越丰富。它取决于显示器或LCD的硬件性能。一般桌面显示器是32.嵌入式设备的bpp可以用fbset 命令来查看。
flags 常见取值有如下(可以取多个值)
SDL_SWSURFACE :数据区建立在系统内存之上
SDL_HWSURFACE:数据区建立在显存之上
SDL_FULLSCREEN:全屏模式
SDL_NOFRAME:取消边框和标题栏
SDL_DOUBLEBUF:硬件双缓冲,必须与SDL_HWSURFACE同时使用。
例: screen = SDL_SetVideoMode( 640,320,32, SDL_SWSURFACE );
1.2 设置窗口标题
void SDL_WM_SetCaption(const char *title, const char *icon);
title 是窗口标题名字,如果是中文,必须是UTF-8编码。
icon 是窗口最小化采用显示文字。也采用UTF-8编码
1.3 把一个Surface数据拷入屏幕
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
这里dst是输出surface(不一定是屏幕Surface,也可以另外一个Surface).
dstrect是src在dst中相应的位置.
1.4 刷新屏幕
int SDL_Flip(SDL_Surface* screen);
把更新后的Surface数据显示在屏幕上,SDL_BlitSurface数据加入屏幕后,不执行这一句,将不会更新到屏幕上显示。
1.5 部分更新屏幕
如果每次都更新整个屏幕,效率这样很低,可以用SDL_UpdateRect更新部分区域
void SDL_UpdateRect(SDL_Surface* screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h);
1.6 设置窗口图标
void SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask);
二.SDL_Surface 基本操作
---------------------------------------------------------------------------
SDL库内置对BMP的处理,因此我们用最常见的就是位图操作来演示Surface操作.
2.1 装入位图
我们采用如下方式生成一个位图Surface.
SDL_Surface *SDL_LoadBMP(const char *file);
注意SDL库不支持其它格式图片处理,如有这个需求,需要用SDL_image来扩展
其中SDL_Surface的宽度,高度就是位图的高,宽
将位图显示在屏幕上,采用SDL_BlitSurface来加入屏幕上。它将原始尺寸显示在屏幕上。如果位图从起点开始显示,宽度和高度超过屏幕。图像会被截掉。
2.2 缩放显示Surface
大部分的应用是需要把Surface 完整缩放显示在整个屏幕之上。SDL有一个未公开的函数SDL_Stretch:
extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,SDL_Surface *dst, SDL_Rect *dstrect);
这个拉伸可能会极大影响图片效果,而且在文档中也明确声明可能不会用。但是实测是可以达到拉伸的效果。
2.3 释放Surface.
一个Surface不使用必须使用SDL_FreeSurface来释放。
3.SDL_Surface 的底层输出
--------------------------------------
在桌面平台一般无需处理原始像素输出。在嵌入式平台,如果分辩率不同,要做一些特殊处理。以下就一段通用代码。分别处理 像素数为8,16,32位的情况。这个后面会使用
像素处理
- void DrawPixel(SDL_Surface *screen, Uint8 R, Uint8 G, Uint8 B)
- {
- Uint32 color = SDL_MapRGB(screen->format, R, G, B);
- if ( SDL_MUSTLOCK(screen) ) {
- if ( SDL_LockSurface(screen) < 0 ) {
- return;
- }
- }
- switch (screen->format->BytesPerPixel) {
- case 1: { /* Assuming 8-bpp */
- Uint8 *bufp;
- bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
- *bufp = color;
- }
- break;
- case 2: { /* Probably 15-bpp or 16-bpp */
- Uint16 *bufp;
- bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
- *bufp = color;
- }
- break;
- case 3: { /* Slow 24-bpp mode, usually not used */
- Uint8 *bufp;
- bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
- *(bufp+screen->format->Rshift/8) = R;
- *(bufp+screen->format->Gshift/8) = G;
- *(bufp+screen->format->Bshift/8) = B;
- }
- break;
- case 4: { /* Probably 32-bpp */
- Uint32 *bufp;
- bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
- *bufp = color;
- }
- break;
- }
- if ( SDL_MUSTLOCK(screen) ) {
- SDL_UnlockSurface(screen);
- }
- SDL_UpdateRect(screen, x, y, 1, 1);
- }