18

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

例如,我有一个程序在启动时会弹出一个包含徽标和版权信息的启动画面。而不是将此图像放在位图文件中并使用 SDL_LoadBMP 将其加载到 SDL_Surface。我想将图像嵌入程序二进制文件中,以阻止有人可能更改启动图像和版权名称。

有没有人对如何做到这一点有任何建议?示例代码会很棒。

4

3 回答 3

18

在可执行文件中嵌入文件很容易,但有一些陷阱,有几种方法可以做到这一点,包括一些可移植和不可移植的方法。

将图像转换为 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

于 2013-08-24T19:41:59.593 回答
4

您可以将图像导出为 .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;
}

我希望这有帮助。

于 2013-10-18T12:08:07.437 回答
1

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

于 2013-08-24T20:08:02.663 回答