如何使用SDL2直接加载嵌入式PNG而非先写入文件?
直接从内存加载嵌入式PNG到SDL2纹理的解决方案
我懂你现在的困扰——每次把嵌入式PNG写入临时文件再加载确实有点多余,完全没必要绕这个弯。问题出在你直接把_binary_flower_png_start传给IMG_LoadTexture,但这个函数只认文件路径字符串,不支持直接读取内存数据。不过SDL2和SDL_image提供了SDL_RWops这个工具,能帮你直接从内存读取资源,彻底跳过文件步骤。
先修正你当前代码里的一个小bug
你当前的fwrite参数顺序是错的,正确调用应该是:
fwrite(_binary_flower_png_start, 1, _binary_flower_png_size, f);
原来的参数顺序不符合fwrite的定义(ptr, size, nmemb, stream),虽然可能碰巧能运行,但这是潜在的隐患。
直接从内存加载的实现步骤
核心思路是用SDL_RWFromConstMem把嵌入式PNG数据包装成SDL的IO流对象,再用IMG_LoadTexture_RW加载这个流:
- 删掉所有创建临时文件的代码(
fopen、fwrite、fclose这些) - 用
SDL_RWFromConstMem创建内存流,传入_binary_flower_png_start和_binary_flower_png_size - 调用
IMG_LoadTexture_RW加载纹理,第二个参数传1让SDL自动释放这个RW流对象
修改后的完整代码
#include <stdlib.h> #include <stdio.h> #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> extern const char _binary_flower_png_start[]; extern const int _binary_flower_png_size; int main() { SDL_Event event; SDL_Renderer *renderer = NULL; SDL_Texture *texture = NULL; SDL_Window *window = NULL; SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO); SDL_CreateWindowAndRenderer(500, 500, 0, &window, &renderer); IMG_Init(IMG_INIT_PNG); // 直接从内存加载,跳过临时文件 SDL_RWops *rw = SDL_RWFromConstMem(_binary_flower_png_start, _binary_flower_png_size); if (rw == NULL) { fprintf(stderr, "SDL_RWFromConstMem failed: %s\n", SDL_GetError()); goto cleanup; } texture = IMG_LoadTexture_RW(renderer, rw, 1); // 最后一个参数1表示自动释放rw if (texture == NULL) { fprintf(stderr, "IMG_LoadTexture_RW failed: %s\n", IMG_GetError()); goto cleanup; } // 渲染循环 while (1) { SDL_RenderClear(renderer); // 建议每次渲染前清屏,避免画面残留 SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); if (SDL_PollEvent(&event) && event.type == SDL_QUIT) break; } cleanup: SDL_DestroyTexture(texture); IMG_Quit(); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return EXIT_SUCCESS; }
额外说明
- 我加了错误检查(
SDL_RWFromConstMem和IMG_LoadTexture_RW的返回值判断),调试时能快速定位内存流创建或纹理加载失败的原因 - 渲染循环里加了
SDL_RenderClear,这是个好习惯,不然窗口可能会出现奇怪的画面残留 - 不需要用到
_binary_flower_png_end,因为_binary_flower_png_size已经给出了数据总长度,直接用这个参数就够了
内容的提问来源于stack exchange,提问作者Maxy Mertan
相关产品推荐
相关产品推荐

