SDL在程序可执行文件中嵌入图像

SDL embed image inside program executable

本文关键字:图像 可执行文件 程序 SDL      更新时间:2023-10-16

是否可以使用SDL在程序中嵌入图像,SDL可以在运行时使用。

例如,我有一个程序,它在启动时会弹出一个包含徽标和版权信息的启动屏幕。而不是将此图像保存在位图文件中并使用SDL_LoadBMP将其加载到SDL_Surface。我希望将图像嵌入程序二进制文件中,以防止有人更改启动图像和版权名称。

有人对此有什么建议吗?示例代码会很棒。

在可执行文件中嵌入文件很容易,但也有一些困难,有几种方法可以实现,包括一些可移植和不可移植的方法。

使用#embed

据报道,这将是C23的一部分。它可能也会出现在C++26中。检查编译器是否支持此功能。在未来,这可能是嵌入二进制数据的最便携、最直接的方法。

static const unsigned char IMAGE_DATA[] = {
#embed "myimage.bmp
};

特性建议见WG14 n2592。

优点:最简单,最容易

缺点:您的编译器可能还不支持

将图像转换为C代码

编写一个脚本,将图像转换为C中的常量数组。该脚本在Python中看起来像这样:

#!/usr/bin/env python3
print("static const unsigned char IMAGE_DATA[] = {{{}}};".format(
        ",".join(str(b) for b in open("myimage.bmp", "rb").read())))

只需将输出通过管道传输到一个*.h文件,然后将该文件从另一个文件中包含。您可以使用sizeof(IMAGE_DATA)获取文件的大小。

优点:便携式

缺点:需要安装Python,如果数组对于编译器来说太大,则不起作用,需要在构建系统中添加自定义步骤

将图像转换为对象文件

这更依赖于平台。在带有GNU binutils工具链的平台上(例如Linux),您可以使用objcopy,我认为bin2obj适用于Microsoft工具链。

优点:适用于所有

缺点:不可移植,需要在构建系统中添加自定义步骤,自定义步骤可能很难获得正确的

在GNU binutils工具链上,使用objcopy

objcopy程序允许您指定binary作为输入格式,但您需要显式指定体系结构。。。因此,您必须修改可执行文件的i386和x64版本的命令。

$ objcopy --input binary --output elf32-i386 --binary-architecture i386 
    myimage.bmp myimage.o

您可以使用以下声明从C中获取数据:

// Ignore the fact that these are char...
extern char _binary_myimage_bmp_start, _binary_myimage_bmp_end;
#define MYIMAGE_DATA ((void *) &_binary_myimage_bmp_start)
#define MYIMAGE_SIZE 
    ((size_t) (&_binary_myimage_bmp_end - &_binary_myimage_bmp_start))

使用汇编指令

矛盾的是,在汇编程序中嵌入静态文件相当容易。汇编程序通常具有类似.incbin(与GAS和YASM一起使用)的指令。

优点:适用于所有

缺点:不可移植,不同平台的汇编程序语法不同

(Windows)将文件作为资源嵌入

在Windows上,您可以在EXE中嵌入资源,然后使用库调用获取资源。

优点:如果你在Windows 上,可能最容易

缺点:仅适用于Windows

您可以将图像导出为.xpm格式(在gimp中)并将其包含在代码中。但是您需要SDL_Image.h将其加载为SDL_Surface。

正如本文档中所述,非常简单:

//To create a surface from an XPM image included in C source, use:
SDL_Surface *IMG_ReadXPMFromArray(char **xpm);

C/C++中的一个例子:

#include <SDL/SDL.h>
#include "test.xpm"
#include <SDL/SDL_image.h>
SDL_Surface *image;
SDL_Surface *screen;
int main(int argc, char **argv)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(800,600,32,SDL_SWSURFACE);
    image = IMG_ReadXPMFromArray(test_xpm); //the .xpm image is a char array. "test_xpm" is the name of the char array
    SDL_Rect offset;
    offset.x = 0;
    offset.y = 0;
    SDL_BlitSurface(image,NULL,screen,&offset);
    SDL_Flip(screen);
    SDL_Delay(5000);

    return 0;
}

我希望这能有所帮助。

使用gimp,您可以将图像保存为c代码。

相关文章: