我有一个用C ++编写的小型演示可执行文件,它只依赖于在运行之前加载的一个5kb PNG图像,用于我制作的像素文本。由于这个文件,我需要提供一个ZIP存档而不仅仅是一个可执行文件,这会在下载和“播放”之间产生足够的摩擦,我相信这会阻止一些人试用它。
我的问题是,无论如何都要将PNG文件(以及任何其他文件)真正嵌入到可执行文件或源代码中,以便它是一个文件,可执行文件可以使用它吗?
我能够将PNG解析为字节流,因此不需要将其转换为像素数据。
提前致谢! (存在与此类似标题的其他问题,但他们和他们的答案似乎涉及更具体的问题,并且不是很有帮助)
编辑:编译器是Visual C ++ 2010,这是在Windows上(虽然我想避免使用Windows特定的实用程序)
edit2 :Alf的答案看起来像是最便携的方法,因此我快速编写了一个函数来将PNG文件解析为TXT或头文件,该文件可以作为unsigned char
数组读取。它在这种形式下似乎与PNG文件本身相同,但我的png加载器不接受该数组。从内存加载时,如果重要的话,PNG解析器需要(void * buffer, size_t length)
。
代码如果你想看,但如果你认为它们比这种方法更好,我还会接受其他答案:
void compileImagePNGtoBinary(char * filename, char * output){
FILE * file = fopen(filename, "rb");
FILE * out = fopen(output, "w");
unsigned char buffer[32];
size_t count;
fprintf(out, "#pragma once \n\n static unsigned char TEXT_PNG_BYTES[] = { ");
while(!feof(file)){
count = fread(buffer, 1, 32, file);
for(int n = 0; n < count; ++n){
fprintf(out, "0x%02X, ", buffer[n]);
};
};
fprintf(out, "};");
fclose(file);
fclose(out);
};
最终修改:ImageMagick Alf也提到了我所需要的,谢谢!
答案 0 :(得分:10)
便携式方法是定义类似
的功能typedef unsigned char Byte;
Byte const* pngFileData()
{
static Byte const data =
{
// Byte data generated by a helper program.
};
return data;
}
然后你要做的就是写一个小帮助程序,将PNG文件作为二进制文件读取,并生成C ++花括号初始化文本。 编辑:@awoodland在评论中指出,ImageMagick有一个小帮手程序......
当然,对于特定于Windows的程序,请使用普通的Windows资源方案。
干杯&amp;第h。,
答案 1 :(得分:9)
看看XD:
最后,xd可以读取二进制文件并发出C语言数据 包含文件数据的声明。这很方便 你希望在C程序中嵌入二进制数据。
就个人而言,我会将资源用于Windows,但如果您需要一种不涉及可执行格式知识的真正可移植方式,那么这就是要走的路。 PNG,JPG,等等...
答案 2 :(得分:5)
Base64对文件进行编码并将其放在代码中的某个字符串中;)
答案 3 :(得分:4)
这是依赖于可执行文件的,这意味着依赖于操作系统/编译器。 Windows为此提供了资源系统,如this question中所述。
答案 4 :(得分:3)
您可以将任意文件嵌入到您的计划资源中:(MSDN) User-Defined Resource。
用户定义的资源定义语句定义包含特定于应用程序的数据的资源。数据可以是任何格式,可以定义为给定文件的内容(如果给出文件名参数),也可以定义为一系列数字和字符串(如果指定了原始数据块)。
nameID typeID filename
filename指定包含资源二进制数据的文件的名称。该文件的内容作为资源包含在内。 RC不以任何方式解释二进制数据。程序员有责任确保数据与目标计算机体系结构正确对齐。
完成后,您可以使用LoadResource function访问文件中包含的字节。
答案 5 :(得分:0)
在linux上我使用它。它基于我在尝试做4k演示时发现的几个例子,尽管有点修改。我相信它也适用于Windows,但不适用于默认的VS内联汇编。我的解决方法是#defining一个宏来使用这个代码或@MarkRansom建议的Windows资源系统(工作非常痛苦,但最终确实有效)。
//USAGE: call BINDATA(name, file.txt) and access the char array &name.
#ifndef EMBED_DATA_H
#define EMBED_DATA_H
#ifdef _WIN32
//#error The VS ASM compiler won't work with this, but you can get external ones to do the trick
#define BINDATA #error BINDATA requires nasm
#else
__asm__(
".altmacro\n" \
".macro binfile p q\n" \
" .global \\p\n" \
"\\p:\n" \
" .incbin \\q\n" \
"\\p&_end:\n" \
" .byte 0\n" \
" .global \\p&_len\n" \
"\\p&_len:\n" \
" .int(\\p&_end - \\p)\n" \
".endm\n\t"
);
#ifdef __cplusplus
extern "C" {
#endif
#define BINDATA(n, s) \
__asm__("\n\n.data\n\tbinfile " #n " \"" #s "\"\n"); \
extern char n; \
extern int n##_len;
#ifdef __cplusplus
}
#endif
#endif
#endif