SDL显示图片总结

到现在为止,已经写了好几个显示图片一类的程序  现在就来好好总结一下

首先我们在最开始   是在屏幕上显示一张图片
整个过程如下:
定义两个 SDL_Surface 指针变量   分别是表示窗口和图像  
之后就调用 SDL_Init()进行初始化SDL的子系统
SDL_SetVideoMode()函数是用来设置窗口的
之后就是加载图像(现期的sdl只能加载bmp位图  其他格式需要调用扩展库)调用 SDL_LoadBMP()
在窗口和图像都赋值以后就调用 SDL_BlitSurface(图像 , NULL, 窗口, NULL )将图像映射到窗口
当然现在还不会显示  调用 SDL_Flip(窗口)就可以显示了
SDL_Delay()的作用就是为了延迟显示时间 能够让你看到
完事以后记得 SDL_FreeSurface()释放资源
最后  SDL_Quit()退出就好了

上面的过程其实已经基本上差不多了
第二个程序其实是第一个的优化版本,因为有时候加载的图片与显示的位数不同,所以在现实的时候存在一个隐式的格式转换。比较浪费时间,所以在加载的时候  我们可以读取的时候就把他转一下  就不用在显示的时候转换
主要就是在调用 SDL_LoadBMP() 以后  再调用 SDL_DisplayFormat()

第三个则是引进了扩展库  用来识别更多格式的图片
只是将 SDL_LoadBMP() 改成了 IMG_Load()

——————————————————————————————————————————————
下面就来细化一下上面说的一些函数:
SDL_Surface类型     我们可以在SDL_video.h里面找到它的定义
/** This structure should be treated as read-only, except for 'pixels',
*  which, if not NULL, contains the raw pixel data for the surface.
*这个结构应该被视为只读结构,除了‘像素’,如果不是NULL,它包含表面的原始像素数据。
*/
typedef struct SDL_Surface {
    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 */
    /** Hardware-specific surface info */
    struct private_hwdata *hwdata;
    /** clipping information */
    SDL_Rect clip_rect;            /**< Read-only */
    Uint32 unused1;                /**< for binary compatibility */
    /** Allow recursive locks */
    Uint32 locked;                /**< Private */
    /** info for fast blit mapping to other surfaces */
    struct SDL_BlitMap *map;        /**< Private */
    /** format version, bumped at every change to invalidate blit maps */
    unsigned int format_version;        /**< Private */
    /** Reference count -- used when freeing surface */
    int refcount;                /**< Read-mostly */
} SDL_Surface;
——————————————————————————————————————————————
SDL_Init()函数是用来初始化子系统的   定义在SDL.c文件里面
下面是初始化的子系统
/** @name SDL_INIT Flags
*  These are the flags which may be passed to SDL_Init() -- you should
*  specify the subsystems which you will be using in your application.
*/
/*@{*/
#define    SDL_INIT_TIMER        0x00000001
#define SDL_INIT_AUDIO        0x00000010
#define SDL_INIT_VIDEO        0x00000020
#define SDL_INIT_CDROM        0x00000100
#define SDL_INIT_JOYSTICK    0x00000200
#define SDL_INIT_NOPARACHUTE    0x00100000    /**< Don't catch fatal signals */
#define SDL_INIT_EVENTTHREAD    0x01000000    /**< Not supported on all OS's */
#define SDL_INIT_EVERYTHING    0x0000FFFF
——————————————————————————————————————————————
SDL_SetVideoMode()函数  是用来设置窗口的   定义在SDL_video.c文件中
Set the requested video mode, allocating a shadow buffer if necessary.
设置请求的视频模式,必要时分配阴影缓冲区。

SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)


——————————————————————————————————————————————

SDL_LoadBMP(file)其实调用的 SDL_LoadBMP_RW()
我们可以在SDL_video.h看到
#define SDL_LoadBMP(file)    SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
SDL_LoadBMP_RW()函数的定义在SDL_bmp.c中

——————————————————————————————————————————————

SDL_BlitSurface()函数  感觉是比较重要的一个函数

它的定义在SDL_video.h文件中
/**
* This performs a fast blit from the source surface to the destination
* surface.  It assumes that the source and destination rectangles are
* the same size.  If either 'srcrect' or 'dstrect' are NULL, the entire
* surface (src or dst) is copied.  The final blit rectangles are saved
* in 'srcrect' and 'dstrect' after all clipping is performed.
* If the blit is successful, it returns 0, otherwise it returns -1.
*
* The blit function should not be called on a locked surface.
*
* The blit semantics for surfaces with and without alpha and colorkey
* are defined as follows:
*
* RGBA->RGB:
*     SDL_SRCALPHA set:
*     alpha-blend (using alpha-channel).
*     SDL_SRCCOLORKEY ignored.
*     SDL_SRCALPHA not set:
*     copy RGB.
*     if SDL_SRCCOLORKEY set, only copy the pixels matching the
*     RGB values of the source colour key, ignoring alpha in the
*     comparison.
*
* RGB->RGBA:
*     SDL_SRCALPHA set:
*     alpha-blend (using the source per-surface alpha value);
*     set destination alpha to opaque.
*     SDL_SRCALPHA not set:
*     copy RGB, set destination alpha to source per-surface alpha value.
*     both:
*     if SDL_SRCCOLORKEY set, only copy the pixels matching the
*     source colour key.
*
* RGBA->RGBA:
*     SDL_SRCALPHA set:
*     alpha-blend (using the source alpha channel) the RGB values;
*     leave destination alpha untouched. [Note: is this correct?]
*     SDL_SRCCOLORKEY ignored.
*     SDL_SRCALPHA not set:
*     copy all of RGBA to the destination.
*     if SDL_SRCCOLORKEY set, only copy the pixels matching the
*     RGB values of the source colour key, ignoring alpha in the
*     comparison.
*
* RGB->RGB:
*     SDL_SRCALPHA set:
*     alpha-blend (using the source per-surface alpha value).
*     SDL_SRCALPHA not set:
*     copy RGB.
*     both:
*     if SDL_SRCCOLORKEY set, only copy the pixels matching the
*     source colour key.
*
* If either of the surfaces were in video memory, and the blit returns -2,
* the video memory was lost, so it should be reloaded with artwork and
* re-blitted:
* @code
*    while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) {
*        while ( SDL_LockSurface(image) < 0 )
*            Sleep(10);
*        -- Write image pixels to image->pixels --
*        SDL_UnlockSurface(image);
*    }
* @endcode
*
* This happens under DirectX 5.0 when the system switches away from your
* fullscreen application.  The lock will also fail until you have access
* to the video memory again.
*
* You should call SDL_BlitSurface() unless you know exactly how SDL
* blitting works internally and how to use the other blit functions.
*/
#define SDL_BlitSurface SDL_UpperBlit
可以看出   调用 SDL_BlitSurface()
其实就是在调用 SDL_UpperBlit()我们可以看下这个函数 
他定义在SDL_surface.c中

——————————————————————————————————————————————
SDL_Flip()函数  函数的声明可以看SDL_video.h  定义的话  就在 SDL_video.c
/**
* On hardware that supports double-buffering, this function sets up a flip
* and returns.  The hardware will wait for vertical retrace, and then swap
* video buffers before the next video surface blit or lock will return.
* On hardware that doesn not support double-buffering, this is equivalent
* to calling SDL_UpdateRect(screen, 0, 0, 0, 0);
* The SDL_DOUBLEBUF flag must have been passed to SDL_SetVideoMode() when
* setting the video mode for this function to perform hardware flipping.
* This function returns 0 if successful, or -1 if there was an error.
*/
extern DECLSPEC int SDLCALL SDL_Flip(SDL_Surface *screen);

——————————————————————————————————————————————
SDL_Delay()这个函数  只是看起来简单  但是由于SDL的跨平台性  这个函数的定义就有点复杂了
函数声明在SDL_timer.h
/** Wait a specified number of milliseconds before returning */
extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
定义在SDL_systimer.c
——————————————————————————————————————————————
SDL_FreeSurface()函数
函数定义在SDL_surface.c文件中
——————————————————————————————————————————————
SDL_Quit()函数  与SDL_Init定义在同一个文件(SDL.c)

——————————————————————————————————————————————

SDL_DisplayFormat()函数声明在SDL_video.h中
/**
* This function takes a surface and copies it to a new surface of the
* pixel format and colors of the video framebuffer, suitable for fast
* blitting onto the display surface.  It calls SDL_ConvertSurface()
*
* If you want to take advantage of hardware colorkey or alpha blit
* acceleration, you should set the colorkey and alpha value before
* calling this function.
*
* If the conversion fails or runs out of memory, it returns NULL
*/
extern DECLSPEC SDL_Surface * SDLCALL SDL_DisplayFormat(SDL_Surface *surface);
函数的声明在SDL_video.c
——————————————————————————————————————————————
IMG_Load()函数是扩展库提供的   我这边就不多说了

好的,以下是一个基于 SDL 库的简单命令行音乐播放器的示例代码。该程序支持播放、暂停、停止、上一曲、下一曲、调整音量等功能。 ```c++ #include <iostream> #include <string> #include <SDL.h> using namespace std; // 常量定义 const int VOLUME_INCREMENT = 10; // 调整音量时的增量 const string MUSIC_DIRECTORY = "./music/"; // 音乐文件所在的目录 const string MUSIC_LIST[] = { "music1.mp3", "music2.mp3", "music3.mp3" }; // 音乐文件列表 // 全局变量定义 int currentMusicIndex = 0; // 当前播放的音乐文件在列表中的索引 int volume = 100; // 当前音量 // 函数声明 void playMusic(SDL_AudioDeviceID audioDevice, const string& musicFilename); void pauseMusic(SDL_AudioDeviceID audioDevice); void stopMusic(SDL_AudioDeviceID audioDevice); void adjustVolume(SDL_AudioDeviceID audioDevice, int volumeIncrement); void playNextMusic(SDL_AudioDeviceID audioDevice); void playPreviousMusic(SDL_AudioDeviceID audioDevice); int main(int argc, char* argv[]) { // 初始化 SDL if (SDL_Init(SDL_INIT_AUDIO) != 0) { cerr << "Failed to initialize SDL: " << SDL_GetError() << endl; return 1; } // 打开音频设备 SDL_AudioSpec desiredSpec, obtainedSpec; SDL_zero(desiredSpec); desiredSpec.freq = 44100; desiredSpec.format = AUDIO_S16SYS; desiredSpec.channels = 2; desiredSpec.samples = 2048; desiredSpec.callback = NULL; SDL_AudioDeviceID audioDevice = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, &obtainedSpec, 0); if (audioDevice == 0) { cerr << "Failed to open audio device: " << SDL_GetError() << endl; SDL_Quit(); return 1; } // 播放第一首音乐 playMusic(audioDevice, MUSIC_DIRECTORY + MUSIC_LIST[currentMusicIndex]); // 处理命令行输入 string command; while (true) { cout << "Enter a command (play/pause/stop/volumeup/volumedown/next/previous): "; cin >> command; if (command == "play") { playMusic(audioDevice, MUSIC_DIRECTORY + MUSIC_LIST[currentMusicIndex]); } else if (command == "pause") { pauseMusic(audioDevice); } else if (command == "stop") { stopMusic(audioDevice); } else if (command == "volumeup") { adjustVolume(audioDevice, VOLUME_INCREMENT); } else if (command == "volumedown") { adjustVolume(audioDevice, -VOLUME_INCREMENT); } else if (command == "next") { playNextMusic(audioDevice); } else if (command == "previous") { playPreviousMusic(audioDevice); } else { cout << "Invalid command. Try again." << endl; } } // 关闭音频设备和 SDL SDL_CloseAudioDevice(audioDevice); SDL_Quit(); return 0; } // 播放音乐 void playMusic(SDL_AudioDeviceID audioDevice, const string& musicFilename) { SDL_ClearQueuedAudio(audioDevice); SDL_AudioSpec wavSpec; Uint32 wavLength; Uint8* wavBuffer; if (SDL_LoadWAV(musicFilename.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL) { cerr << "Failed to load music file: " << SDL_GetError() << endl; return; } SDL_QueueAudio(audioDevice, wavBuffer, wavLength); SDL_FreeWAV(wavBuffer); SDL_PauseAudioDevice(audioDevice, 0); cout << "Playing " << musicFilename << endl; } // 暂停音乐 void pauseMusic(SDL_AudioDeviceID audioDevice) { SDL_PauseAudioDevice(audioDevice, 1); cout << "Music paused" << endl; } // 停止音乐 void stopMusic(SDL_AudioDeviceID audioDevice) { SDL_ClearQueuedAudio(audioDevice); SDL_PauseAudioDevice(audioDevice, 1); cout << "Music stopped" << endl; } // 调整音量 void adjustVolume(SDL_AudioDeviceID audioDevice, int volumeIncrement) { volume += volumeIncrement; if (volume > 128) { volume = 128; } else if (volume < 0) { volume = 0; } SDL_Volume(audioDevice, volume / 128.0f); cout << "Volume adjusted to " << volume << endl; } // 播放下一首音乐 void playNextMusic(SDL_AudioDeviceID audioDevice) { currentMusicIndex = (currentMusicIndex + 1) % (sizeof(MUSIC_LIST) / sizeof(MUSIC_LIST[0])); stopMusic(audioDevice); playMusic(audioDevice, MUSIC_DIRECTORY + MUSIC_LIST[currentMusicIndex]); } // 播放上一首音乐 void playPreviousMusic(SDL_AudioDeviceID audioDevice) { currentMusicIndex--; if (currentMusicIndex < 0) { currentMusicIndex = sizeof(MUSIC_LIST) / sizeof(MUSIC_LIST[0]) - 1; } stopMusic(audioDevice); playMusic(audioDevice, MUSIC_DIRECTORY + MUSIC_LIST[currentMusicIndex]); } ``` 注意:该示例程序需要在包含 SDL 库的环境中编译运行。具体的编译方法和配置方式可以参考 SDL 官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值