将png转换为sdl的c标头

我想说,我已经在互联网上搜索过这个话题,但它并不适用于我的情况。

我正在对使用C的游戏进行修改,我正在编辑用于游戏的图像,但是图像需要转换为c标头才能使它们正常工作。 该游戏是多平台的,通过NDK为Windows和Android构建。

我实际上完成了一些编辑,使用“ 在SDL中使用gimp导出的.c / .h图像 ”作为我的解决方案的基础,使用mbin2h,它将任何二进制文件转换为适合C头的内容。 它适用于Android版本,但不适用于主要的跨平台C版本。

这是一个示例代码:

这就是mbin2h通常输出的内容:

0x89, 'P', 'N', 'G', 0xD, 0xA, 0x1A, 0xA, 0x0, 0x0, 0x0, 0xD, 'I', 'H', 'D', 'R' 

这是源于原始来源:

 "\x89""PNG""\15\12\32\12\0\0\0\15""IHDR" 

我不知道他们用什么程序将PNG转换为头文件。 正如你们中的一些人指出的那样,它是hex,ASCII字符和八进制值的组合。

问题是如何将png转换为类似于原始代码的头文件? 为了方便其他人搞清楚,我在zip文件中放置了原始图像,原始标题和mbin2h生成的标题: image problem.zip – 319.73

这实际上是OpenBOR,我只想修改菜单图像,但因为我不知道如何编程,所以我需要一些帮助,抱歉。

编辑:我没有看到有一个答案按钮,我会把答案提出来。 对不起大家。

将二进制转换为C兼容数据并不困难,尽管我想知道为什么创建的结构不必要地复杂。 然后,如果源代码的其余部分需要这种特定格式,则只需复制原始结构并填写正确的值。

..它是hex,ASCII字符和八进制值的组合..

这只会使源文件尽可能短。 没有其他理由; 整个图像也可以写成\x..hex代码,甚至是小数。

使头文件尽可能小是一个很好的额外挑战。 除了原版之外,我确保没有一行超过100个字符; 仍然,通过使用更多“最短的替代品”,对于测试图像,我的代码仅生成1,626行,其中原始版本为1,921; 减少18%!

用法:programName input.png

它将用.h替换输入文件的.png部分,并将此输出写入当前文件夹。 适用于OSX,我想它应该在其他类似* nix的系统上编译,因为我试图将自己限制为Posix文件I / O. 无论是否包括Windows都被称为“为读者锻炼”。

 #include  #include  #include  #include  #include  #define MAX_LINE_LENGTH 100 int main (int argc, char **argv) { FILE *f_in, *f_out; char *name_ptr,*ptr; off_t i; struct stat st; char out_name[FILENAME_MAX]; unsigned char png_byte, last_byte_octal, output_length; if (argc != 2) { fprintf (stderr, "this requires an input file\n"); return -1; } f_in = fopen (argv[1], "rb"); if (!f_in) { fprintf (stderr, "this requires the input file to exist\n"); return -1; } if (stat(argv[1], &st)) { fprintf (stderr, "this requires the input file to have no problems\n"); return -1; } name_ptr = strrchr (argv[1], '/'); // *nix path if (!name_ptr) name_ptr = strrchr (argv[1], '\\'); // Wind*ws path if (name_ptr) name_ptr++; else name_ptr = argv[1]; if (!*name_ptr || strlen(name_ptr) >= FILENAME_MAX) { fprintf (stderr, "this requires a reasonable length for the file name\n"); return -1; } strcpy (out_name, name_ptr); ptr = out_name; while (*ptr) { *ptr = tolower(*ptr); ptr++; } ptr = strrchr (out_name, '.'); if (*ptr) strcpy (ptr, ".h"); else strcat (out_name, ".h"); f_out = fopen (out_name, "w"); if (!f_out) { fprintf (stderr, "this requires the output file to be created\n"); return -1; } fprintf (stderr, "creating %s, please hold on.\n", out_name); ptr = out_name; while (*ptr) { if (*ptr == '.') *ptr = '_'; ptr++; } for (i=0; i<2; i++) { fprintf (f_out, "#%s", !i ? "ifndef" : "define"); fprintf (f_out, " _"); ptr = out_name; while (*ptr) { fprintf (f_out, "%c", toupper(*ptr)); ptr++; } fprintf (f_out, "_\n"); } fprintf (f_out, "\n" "static const struct {\n" "\tsize_t size;\n" "\tunsigned char data [%lu];\n" "} ", (unsigned long)st.st_size); ptr = name_ptr; while (*ptr) { if (*ptr == '.') fprintf (f_out, "_"); else fprintf (f_out, "%c", tolower(*ptr)); ptr++; } fprintf (f_out, " = {\n" "\t%lu,\n\"", (unsigned long)st.st_size); last_byte_octal = 0; output_length = 1; for (i=0; i= MAX_LINE_LENGTH) { fprintf (f_out, "\"\n\""); output_length = 3; } fprintf (f_out, "\\\\"); last_byte_octal = 0; } else if (png_byte == 9) { output_length += 2; if (output_length >= MAX_LINE_LENGTH) { fprintf (f_out, "\"\n\""); output_length = 3; } fprintf (f_out, "\\t"); last_byte_octal = 0; } else if (png_byte < ' ' || png_byte == '\"') { output_length += (png_byte < 8) ? 2 : 3; last_byte_octal = 1; if (output_length >= MAX_LINE_LENGTH) { fprintf (f_out, "\"\n\""); output_length = (png_byte < 8) ? 3 : 4; } fprintf (f_out, "\\%o", png_byte); } else if (png_byte > '~') { output_length += 4; if (output_length >= MAX_LINE_LENGTH) { fprintf (f_out, "\"\n\""); output_length = 5; } fprintf (f_out, "\\x%X", png_byte); last_byte_octal = 1; } else { output_length += (last_byte_octal && isxdigit(png_byte)) ? 3 : 1; if (output_length >= MAX_LINE_LENGTH) { fprintf (f_out, "\"\n\""); output_length = 2; last_byte_octal = 0; } if (last_byte_octal && isxdigit(png_byte)) fprintf (f_out, "\"\""); fprintf (f_out, "%c", png_byte); last_byte_octal = 0; } } fprintf (f_out, "\"\n};\n\n#endif\n"); fclose (f_in); fclose (f_out); fprintf (stderr, "done.\n"); return 0; } 

我不知道mbin2h是什么(即使我猜它是做什么的)。 我建议你修改你的构建(例如你的Makefile )来生成一些image.cdata文件,并带有一个命令

  mbin2h image.png > image.cdata 

然后有一个C文件包含(接近其开头,以及稍后的其他一些function)

  const char image_data[] = { #include "image.cdata" }; 

然后使用image_data调用适当的例程,可能是sizeof(image_data) ; 可能根据这个答案类似的东西

  SDL_RWops * z = SDL_RWFromMem(image_data,sizeof(image_data)); 

当然,该代码应该出现在与上面的const char image_data[]定义相同的C文件中(并且该定义之后)。

PS。 当5gon12eder回答你应该更喜欢hexdump到你的mbin2h

除了@BasileStarynkevitch的答案和回复你的评论,要求“脚本”:你可以生成所述包含文件image.cdata例如使用Posix hexdump实用程序。 在你的makefile中:

 image.cdata: image.png hexdump --format='8/1 " 0x%02x," "\n"' $< > $@ 

hex格式当然不是最节省空间的格式。 如果你想要改善这一点,请阅读man hexdump

我终于解决了! 正如@Basile和@ 5gon12eder所建议的那样,我在android构建中使用了类似的方法:

 char openbor_menu_480x272_png[32851]={ ... }; 

我将它声明为char并添加了数组大小。 ...是mbin2h的输出。 hexdump方法也可以,但您可能需要手动计算数组大小。

然后我发现用于解码标头的代码在OpenBOR代码中进行映像并且这样做:

 // Read Logo or Menu from Array. if(!type) bgscreen = pngToScreen(isWide ? (void*) openbor_logo_480x272_png.data : (void*) openbor_logo_320x240_png.data); else //CRxTRDude - Removed '.data' since it doesn't use it anyway. bgscreen = pngToScreen(isWide ? (void*) openbor_menu_480x272_png : (void*) openbor_menu_320x240_png); 

我没有编辑徽标图片,所以它保持不变。

编译它,它的工作原理! 显然,由于android和跨平台构建都使用相同的PNG解码器,它实际上也完成了这项工作。

但事实上,@ Jongware实际上制作了一个C脚本,实际上看起来与原版的c标题相似并且有效! 他还说,之所以这样,就是为了大小,这会产生比mbin2h实际上更小的输出。

“除了原版之外,我确保没有单行超过100个字符;不过,通过使用更多’最短的替代品’,对于测试图像,我的代码只生成1,626行,原始版本为1,921;减少18%”

他是真的,虽然有一件事,标题的大小确实减少到18%,但是当它编译时,apk大小虽然没有改变,但是很高兴注意到这实际上也很好地复制了原始代码,使其略小。

无论如何,谢谢你的回答,我很抱歉,如果我误解了那么多。