|
Packing Images into EXE files and reading them out again? |
SomeoneElse
Member #14,288
May 2012
|
(Using Windows and Allegro 5.0.6 here) |
SiegeLord
Member #7,827
October 2006
|
EDIT: Actually nevermind, that was stupid. Just put the contents of your file into this kind of form: const char my_bitmap = {0xff, 0x0f ...}; (you can write a simple program that fopen's the file and outputs a .c file with those contents). Then you'd mount that my_bitmap pointer with the memfile addon and then use al_load_bitmap_f to load the actual bitmap. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Mark Oates
Member #1,146
March 2001
|
The downside is that that it will dramatically inflate the size of the file, so it's mostly only practical for smaller image files. -- |
LennyLen
Member #5,313
December 2004
|
I wrote some code for extracting BMP files from .exe files into Allegro bitmaps. There's an A4.0 version that shouldn't be too difficult to update to A5.0. Unfortunately, my motherboard has died, so I can't upload it here, but the uploaded version in this thread should still work.
|
SiegeLord
Member #7,827
October 2006
|
Mark Oates said: The downside is that that it will dramatically inflate the size of the file, so it's mostly only practical for smaller image files. Are you sure? For me the exe size increases exactly by the amount of the file I encode in the way I suggested in my post. Here's the generator I used (haven't actually tested to see if it actually loads the files though ): 1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4
5int main(int argc, char** argv)
6{
7 if(argc < 3)
8 {
9 printf("Usage:\n%s infile outfile_no_ext\n", argv[0]);
10 exit(-1);
11 }
12
13 FILE* infile = fopen(argv[1], "r");
14 if(infile == 0)
15 {
16 printf("Error opening %s for reading.\n", argv[1]);
17 exit(-1);
18 }
19
20 char* outfilename = malloc(strlen(argv[2] + 3));
21 sprintf(outfilename, "%s.c", argv[2]);
22 FILE* outfile = fopen(outfilename, "w");
23 if(outfile == 0)
24 {
25 printf("Error opening %s for writing.\n", outfilename);
26 exit(-1);
27 }
28
29 fputs("#include \"allegro5/allegro_memfile.h\"\n", outfile);
30 fputs("static const unsigned char _filedata[] = {", outfile);
31
32 unsigned char byte;
33 size_t size = 0;
34 while(fread(&byte, 1, 1, infile) == 1)
35 {
36 if(size > 0)
37 fputs(", ", outfile);
38
39 char hex[5];
40 sprintf(hex, "0x%X", byte);
41 fputs(hex, outfile);
42 size++;
43 }
44 fputs("};\n", outfile);
45
46 char size_string[256];
47 sprintf(size_string, "%zd", size);
48
49 fputs("ALLEGRO_FILE* load_", outfile);
50 fputs(argv[2], outfile);
51 fputs("()\n{\n return al_open_memfile((void*)_filedata, ", outfile);
52 fputs(size_string, outfile);
53 fputs(", \"w\");\n}\n", outfile);
54
55 fclose(infile);
56 fclose(outfile);
57}
"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Matthew Leverton
Supreme Loser
January 1999
|
If he was referring to the size of the C source file vs the image file, then his observation is both true and irrelevant. |
SomeoneElse
Member #14,288
May 2012
|
Wow, SiegeLord's method seems rather straight-forward now that I see what's going on. But, it requires a separate program and only works with bitmaps and simple data/text. As Mark pointed out, it requires a huge c file, and if you want to change it, you have to recompile the entire program connected to it (because you have to #include it to reference it). However, while browsing the Allegro source code (I can't even remember why), I came up with another idea. What if I just made an extension, in a sense, that created ALLEGRO_FILE instances that could read from the EXE's resources themselves? I made some code that should do just that. I hope. I'll test it out in the morning and let you know how it goes, but if it works it should let you include any kind of data file in the resources of the EXE and read them through Allegro's normal functions without anything more complicated than setting an RC definition. Plus, if you make changes, you're only recompiling the RC script, so it's faster. (right? I think this is how the C++ linker works) (I'd post the code here, but it'd be 200 lines. I think that's a little much.) |
Arthur Kalliokoski
Second in Command
February 2005
|
NASM can include binary blobs, you'd have to relink whenever it changed. I did this just last week with a 4+Mb text file to avoid having to get the file size, malloc(), read in in, etc. It was to test a word wrap function on the king james bible. 1incbin.asm
2
3section .data
4
5global TEXTER
6global ENDTEXT
7
8TEXTER:
9incbin "kjv12.txt"
10ENDTEXT:
11
12*********************** 13
14relevant parts of t.c
15
16extern char TEXTER;
17extern char ENDTEXT;
18
19result = wrap(&TEXTER,&finallines,&ENDTEXT-&TEXTER,TEXTLEN);
They all watch too much MSNBC... they get ideas. |
SiegeLord
Member #7,827
October 2006
|
SomeoneElse said: But, it requires a separate program And what do you think dat2c was . Quote: only works with bitmaps and simple data/text It works for any file type. The only issue is that you have to use it through the Allegro file routines. This means it can be any file Allegro can read, but also any file other libraries can read as long as you can override their file interface. Quote: (because you have to #include it to reference it). Ever heard of header files? It'll work for this method too, I just didn't include a header generation code in my code. It'll just contain the ALLEGRO_FILE* load_foo(); function. Quote: read them through Allegro's normal functions without anything more complicated than setting an RC definition. So it'll have the same limitations as my method . EDIT: Also, are these resource scripts even available under Linux? The method I presented is 100% cross-platform as far as I can tell. I also looked around a bit, and turns out there is a Linux program does more or less what my little code snipped did: xdd -i some_file out.c It'll produce the same static array (and a length variable) as my code, but without the nice loading function. Lastly, it turns out you can directly encode a file into an object file bypassing the compilation step. This time the exact procedure is compiler specific, so if you're not using GCC it might be a bit too much: linky. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
SomeoneElse
Member #14,288
May 2012
|
Hehe, I was really tired last night when I posted that. *embarrassed Yes, your method does work with any file-type and mine has the same limitations as yours, if not more. I suppose what I was getting at was that with your method, the file has to be run through an external program and included as a C file (a header file can be used for compiling efficiency), which is a little less straight-forward than simply including it in the resource files. It is, however, more cross-platform compatible as well as much better protected than mine, and it works just as well. Thank you very much, that was very helpful! I'm sorry if my ill-formed words offended you. So, conclusion (for easy searches): To pack an image/other file into an EXE/other executable and still use it in Allegro 5, include the file as a byte[] constant in a C file in your code and use the memfile addon to pretend it's a file. Continue with normal Allegro functions. P.S., I tested my program this morning and it worked! I could include any kind of data file in the resources and read it out perfectly fine. I didn't try to break it, but it works fine for normal operations. Accessing EXE resources may be useful in any case, so if anyone wants the code I'll be glad to hand it out. It's just a C file and a header. |
Mark Oates
Member #1,146
March 2001
|
Matthew Leverton said: If he was referring to the size of the C source file vs the image file, then his observation is both true and irrelevant. Unless you're distributing the source. But yes, that's what I was saying. -- |
Audric
Member #907
January 2001
|
There is a method with GCC, it works on Windows, Linux etc: |
Arthur Kalliokoski
Second in Command
February 2005
|
Audric said: ld -r -b binary -o myimage.o myimage.png Thanks! They all watch too much MSNBC... they get ideas. |
Mark Oates
Member #1,146
March 2001
|
-- |
Arthur Kalliokoski
Second in Command
February 2005
|
I was thinking the ld method couldn't give information on the size of the binary blob, but this SO page says it can. It could be inconvenient with namespaces though, seeing as how the variable names depend on the filename. They all watch too much MSNBC... they get ideas. |
weapon_S
Member #7,859
October 2006
|
If I understand correctly, the data will be loaded into memory as if it were a global variable. It might be nifty, if somebody would know a way to access a tar or (uncompressed) zip archive this way (only one file gets linked in; file system like access). |
SiegeLord
Member #7,827
October 2006
|
weapon_S said: It might be nifty, if somebody would know a way to access a tar or (uncompressed) zip archive this way (only one file gets linked in; file system like access). PhysFS has a function for this, PHYSFS_mountMemory. You'd mount that memory, setup the PhysFS interface via the PhysFS addon and every function in Allegro will work transparently with that archive. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
weapon_S
Member #7,859
October 2006
|
Thanks for posting that. I had trouble navigating their docs. |
|