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

C++ SDL在程序可执行文件中嵌入图像,c++,c,image,bitmap,sdl,C++,C,Image,Bitmap,Sdl,是否可以使用SDL在程序中嵌入图像,SDL可以在运行时使用 例如,我有一个程序,在启动时显示一个包含徽标和版权信息的启动屏幕。而不是将此图像保存在位图文件中并使用SDL_LoadBMP将其加载到SDL_曲面。我希望将图像嵌入到二进制程序中,以阻止有人可能更改splash图像和版权名称 有人对此有什么建议吗?示例代码会很好。在可执行文件中嵌入文件很容易,但有一些问题,有几种方法可以解决,包括一些可移植和不可移植的方法 将图像转换为C代码 编写一个脚本,将图像转换为C语言中的常量数组。该脚本在Pyt

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

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


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

在可执行文件中嵌入文件很容易,但有一些问题,有几种方法可以解决,包括一些可移植和不可移植的方法

将图像转换为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\u 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上使用gimp才能将图像保存为c代码。

您可以将图像导出为.xpm格式(gimp)并将其包含到代码中。但需要SDL_Image.h将其作为SDL_曲面加载

正如在doc中一样,它非常简单:

//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;
}
#包括
#包括“test.xpm”
#包括
SDL_表面*图像;
SDL_表面*屏幕;
int main(int argc,字符**argv)
{
SDL_Init(SDL_Init_EVERYTHING);
屏幕=SDL_设置视频模式(800600,32,SDL_表面);
image=IMG\u ReadXPMFromArray(test\u xpm);//该.xpm映像是一个字符数组。“test\u xpm”是字符数组的名称
垂直偏移量;
偏移量x=0;
偏移量y=0;
SDL_BlitSurface(图像、空值、屏幕和偏移);
SDL_翻转(屏幕);
SDL_延迟(5000);
返回0;
}

我希望这能有所帮助。

顺便说一句:如果有人想改变他们的启动屏幕,他们会改变你的启动屏幕。这不应该是你做这件事的唯一动机。这是真的,如果有人真的想做,他们可能会。然而,我的另一个动机是,该程序是一个小型工具,需要便于携带,便于计算机技能较低的人使用,因此,将整个程序作为一个文件将比必须位于正确位置的小图像文件夹更可取。这当然是可能的(不是微不足道的,但可能的)。在我看来,一个经过适当配置的函数,再加上一个对的调用,可以从任何配置它的地方提取一个映像,包括编译时构建的静态内部缓冲区。这是否“解决”了您正在识别的问题是另一个问题。请看一下这些是如何工作的,根据我的理解,如果我在源代码中将位图图像转换为字符数组。我可以使用这些命令让它在运行时从const变量加载位图?@Scott确切地说,对于获取静态图像的方法,Dietrich有以下一些选项。一旦可执行文件中有bin格式的静态图像,只需设置
SDL_RWOps
以使用自定义函数集(由您编写),该函数集使用该图像作为其数据“源”。你明白了。我曾经考虑过在windows上使用资源,但是我的程序是跨平台的,所以我在寻找一个更通用的解决方案。由于我缺乏汇编知识,而且图像很小,我想我可以使用“将图像转换为C”选项。但是,如果您能为我指出正确的方向,我不介意更多地了解对象文件方法。我的主要开发平台是linux。当然,我添加了更多关于如何使用
objcopy
的说明。非常感谢。这个问题将成为我编程时非常有用的资源。我非常感激:D…或者您可以将图像保存为ppm,将ppm加载程序添加到项目中,并将图像作为文本字符串嵌入到代码中。您可以使用Qt4资源系统,它是跨平台的,支持将图像嵌入到应用程序中。太棒了!但是当我获得了图像.h < /C>文件时,如何在C++中使用它?例如,通常在qt中,我可以将一个字符串设置为图像文件路径(
string str1=str0+“splash.png”;QPixmap pixmap(str1.c_str());
)。我现在应该如何处理
image.h
文件?感谢这是真的,但是gimp只导出原始像素数据。然而,我需要以正确的图像格式保存文件,以便在SDL中使用。