SDL2 图片加载 —— PNG/JPG/BMP 怎么画到屏幕上
两个层次
SDL2 加载图片分两步:
- SDL_image 库:把磁盘上的 PNG、JPG、BMP 读进内存,转成
SDL_Surface(CPU 端的像素数组) - SDL_Texture:把 Surface 上传到 GPU,才能在渲染器上高效绘制
如果只用 SDL2 核心库,只能加载 BMP 格式(SDL_LoadBMP)。要加载 PNG/JPG 需要额外的 SDL_image 扩展库。
安装 SDL_image
包管理器搜索「SDL_image」或「sdl2-image」。部分版本的 Cxxdroid 会把 SDL_image 作为 SDL2 的依赖自动装上。
CMake 链接:
find_package(SDL2_image REQUIRED)
target_link_libraries(mygame PRIVATE SDL2::SDL2 SDL2_image::SDL2_image)
加载流程
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG); // 初始化 PNG 支持
SDL_Window *win = SDL_CreateWindow("Image",
0, 0, 320, 480, SDL_WINDOW_SHOWN);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, 0);
// 1. 加载图片到 Surface
SDL_Surface *surf = IMG_Load("test.png");
if (!surf) {
// 加载失败
}
// 2. Surface → Texture(上传到 GPU)
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, surf);
SDL_FreeSurface(surf); // Surface 可以释放了
// 3. 渲染 Texture
SDL_RenderCopy(ren, tex, nullptr, nullptr);
SDL_RenderPresent(ren);
SDL_Delay(3000);
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
IMG_Quit();
SDL_Quit();
return 0;
}
文件路径问题(Cxxdroid 特有)
这是新手最容易踩的坑。图片文件放哪?程序运行时用什么路径访问?
默认工作目录:Cxxdroid 编译运行的可执行文件,默认工作目录是项目的 build 目录(应用内部存储)。
所以如果你的项目结构是:
项目名/
├── main.cpp
├── test.png ← 图片在这里
└── build/ ← 可执行文件运行时在这里
代码里写 IMG_Load("test.png") 会找不到文件——因为运行目录是 build/,而图片在项目根目录。
解决方案:
- 把图片复制到 build/ 目录:最简单但每次重新编译可能会丢
- 用相对路径向上一级:
IMG_Load("../test.png") - 拷到 Android 公共目录:
/sdcard/Pictures/然后绝对路径加载:IMG_Load("/sdcard/Pictures/test.png") - 2026 新版 SAF:支持 Storage Access Framework,可以选择外部存储目录授权,路径处理更灵活
渲染 Texture 时的参数
SDL_RenderCopy(ren, tex, srcRect, dstRect) 有两个矩形参数:
srcRect:从源图片的哪一部分截取(填nullptr= 整张图)dstRect:渲染到屏幕的哪个位置和大小(填nullptr= 原尺寸绘制到左上角)
SDL_Rect src = {0, 0, 64, 64}; // 从源图截取左上角 64×64
SDL_Rect dst = {100, 200, 128, 128}; // 渲染到屏幕 (100,200) 位置,放大到 128×128
SDL_RenderCopy(ren, tex, &src, &dst);
旋转与翻转
SDL_RenderCopyEx 增加了旋转角度、翻转标志:
SDL_RenderCopyEx(ren, tex, nullptr, &dst,
45.0, // 旋转 45 度
nullptr, // 旋转中心(nullptr = 矩形中心)
SDL_FLIP_NONE); // SDL_FLIP_HORIZONTAL / SDL_FLIP_VERTICAL / SDL_FLIP_NONE
内存管理
加载的 Texture 用完记得释放:
SDL_DestroyTexture(tex);
Texture 是 GPU 内存,不及时释放会导致显存不足(Android 设备的 GPU 显存很有限)。