在前面,我们已经创建了窗口和初始化了背景,接下来,我们为窗口添加我们喜欢的背景。
下面的链接可以查看前面的创建窗口和初始化背景
1.初始化`SDL_image `以支持 JPG 格式
#include <SDL_image.h>
// 初始化 SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL视频子系统不能被初始化, SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 初始化 SDL_image 以支持 JPG 格式
if (!(IMG_Init(IMG_INIT_JPG) & IMG_INIT_JPG)) {
printf("SDL_image 不能被初始化! SDL_image Error: %s\n", IMG_GetError());
return -1;
}
在SDL库中自带的导入图片只能导入bmp格式的图片,这时我们就需要引入扩展库‘SDL_image.h’,它提供了导入其他图片的功能。
目前SDL_image库支持四中格式:
IMG_INIT_JPG
IMG_INIT_PNG
IMG_INIT_TIF
IMG_INIT_WEBP
`IMG_Init()` 函数用于初始化 `SDL_image` 库以支持特定的图像格式。
函数括号里面填写我们指定要支持的图像格式,我们还可以使用按位或 (`|`) 操作符组合多个支持的图像格式。
IMG_INIT()函数将返回一个整数,也就是`IMG_INIT_JPG`的值(位掩码),而使用与 (`&`) 操作符是检查`IMG_Init(IMG_INIT_JPG)` 的返回值是否包含 `IMG_INIT_JPG` 的值。
初始化成功后,窗口就能够支持JPG图片被渲染出来。
2.加载背景图片
// 创建渲染器
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
printf("渲染器不能被创造! SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 加载背景图片
SDL_Surface* background_surface = IMG_Load("xiaomu.jpg"); //填写本地图片地址
if (!background_surface) {
printf("xiaomu.jpg 不能被加载! SDL_image Error: %s\n", IMG_GetError());
return -1;
}
通过IMG_Load()函数来加载我们的图片,并将返回图片数据的`SDL_Surface`结构的指针类型赋值给变量`background_surface`。
`SDL_Surface` 结构包含了用于描述图像的信息,如像素格式、宽度、高度以及指向实际像素数据的指针等。
这一步,我们的图片就加载完成了。
3.将`SDL_Surface`结构转换成`SDL_Texture`结构
SDL_Texture* background_texture = SDL_CreateTextureFromSurface(renderer, background_surface);
if (!background_texture) {
printf("不能将Surface转换为Texrure! SDL_Error: %s\n", SDL_GetError());
return -1;
}
//释放Surface占用的内存
SDL_FreeSurface(background_surface);
`SDL_Surface` 是一个内存中的图像数据结构,通常用于存储未经优化的原始图像数据。它可以用于简单的图像操作,如图像加载、颜色转换等。
而`SDL_Texture` 是一种专为渲染优化的数据结构,通常用于 GPU(`图形处理器`,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上图像运算工作的微处理,但它不仅仅只是运用在处理图像上,这里我就不过多描述了) 加速的渲染操作。它更适合现代图形硬件,可以在渲染时提供更高的性能。
通过`SDL_CreateTextureFromSurface()`函数,就能将图片的Surface结构优化成Textture结构,
然后将Surface对象释放,防止内存泄漏。
这时我们的图像数据就转换成了纹理数据,也就能将其投射至窗口显示了。
4.将纹理数据复制到渲染目标(即窗口上)
SDL_RenderCopy(renderer, //渲染目标
background_texture, //要复制的纹理
NULL, //选择输入纹理的一块矩形区域作为输入。设置为NULL的时候整个纹理作为输入
NULL); //选择渲染目标的一块矩形区域作为输出。设置为NULL的时候整个渲染目标作为输出。
`SDL_RenderCopy()`允许屏幕上显示纹理
5.总的代码
#include <SDL.h>
#include <SDL_image.h>
#include<stdio.h>
int main(int argc, char* argv[]) {
// 初始化 SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL视频子系统不能被初始化, SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 初始化 SDL_image 以支持 JPG 格式
if (!(IMG_Init(IMG_INIT_JPG) & IMG_INIT_JPG)) {
printf("SDL_image 不能被初始化! SDL_image Error: %s\n", IMG_GetError());
return -1;
}
// 创建窗口
SDL_Window* window = SDL_CreateWindow(
"SDL Background ",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
650, 600,
SDL_WINDOW_SHOWN
);
if (!window) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 创建渲染器
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
printf("渲染器不能被创造! SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 加载背景图片
SDL_Surface* background_surface = IMG_Load("xiaomu.jpg");
if (!background_surface) {
printf("xiaomu.jpg 不能被加载! SDL_image Error: %s\n", IMG_GetError());
return -1;
}
// 将图片数据转换成纹理数据
SDL_Texture* background_texture = SDL_CreateTextureFromSurface(renderer, background_surface);
if (!background_texture) {
printf("不能将Surface转换为Texrure! SDL_Error: %s\n", SDL_GetError());
return -1;
}
// 释放Surface占用的内存
SDL_FreeSurface(background_surface);
// 主循环
bool quit = false;
SDL_Event event;
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
// 清屏
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// 渲染背景
SDL_RenderCopy(renderer, background_texture, NULL, NULL);
// 呈现内容
SDL_RenderPresent(renderer);
}
// 清理资源
SDL_DestroyTexture(background_texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return 0;
}
6.运行后的结果
到此,我们的背景图片就设置成功了。