├── .gitignore ├── test ├── test.bin └── test.c ├── .clang-format ├── Makefile ├── LICENCE ├── README.md └── bin2c.c /.gitignore: -------------------------------------------------------------------------------- 1 | bin2c 2 | test/test_header.h 3 | test/test 4 | -------------------------------------------------------------------------------- /test/test.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwilymk/bin2c/HEAD/test/test.bin -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Mozilla 3 | IndentWidth: 4 4 | SpaceAfterCStyleCast: true 5 | PointerAlignment: Right 6 | ... 7 | 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS := -O2 -Wall -Wextra 2 | 3 | .PHONY: all 4 | all: bin2c 5 | 6 | .PHONY: clean 7 | clean: 8 | rm -f bin2c test/test test/test_header.h 9 | 10 | bin2c: bin2c.c 11 | $(CC) $(CFLAGS) -o $@ $< 12 | 13 | test/test_header.h: test/test.bin bin2c 14 | ./bin2c $< $@ test_array 15 | 16 | test/test: test/test.c test/test_header.h 17 | $(CC) $(CFLAGS) -o $@ $< 18 | 19 | .PHONY: test 20 | test: test/test test/test.bin 21 | test/test test/test.bin 22 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test_header.h" 5 | 6 | int 7 | main(int argc, char **argv) 8 | { 9 | if (argc != 2) { 10 | fprintf(stderr, "Expected 1 argument, got %i\n", argc - 1); 11 | return 1; 12 | } 13 | 14 | FILE *f = fopen(argv[1], "rb"); 15 | 16 | int length = 0; 17 | // We know the file has size 100 bytes so don't need to worry about 18 | // half full buffers. Also, we need to handle endianness of the 19 | // machine so we can't just read one byte at a time, but must instead 20 | // read 2 bytes at a time... 21 | char buff[2]; 22 | 23 | while ((fread(buff, 1, 2, f)) == 2) { 24 | assert((buff[0] & 0xff) == (test_array[length] & 0xff)); 25 | assert((buff[1] & 0xff) == (test_array[length + 1] & 0xff)); 26 | 27 | length += 2; 28 | } 29 | 30 | assert(length == test_array_length); 31 | fclose(f); 32 | 33 | printf("All tests successful\n"); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The person or persons who have associated work with this document (the "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of his knowledge, the work of authorship identified is in the public domain of the country from which the work is published, or (b) hereby dedicates whatever copyright the dedicators holds in the work of authorship identified below (the "Work") to the public domain. A certifier, moreover, dedicates any copyright interest he may have in the associated work, and for these purposes, is described as a "dedicator" below. 2 | 3 | A certifier has taken reasonable steps to verify the copyright status of this work. Certifier recognizes that his good faith efforts may not shield him from liability if in fact the work certified is not in the public domain. 4 | 5 | Dedicator makes this dedication for the benefit of the public at large and to the detriment of the Dedicator's heirs and successors. Dedicator intends this dedication to be an overt act of relinquishment in perpetuity of all present and future rights under copyright law, whether vested or contingent, in the Work. Dedicator understands that such relinquishment of all rights includes the relinquishment of all rights to enforce (by lawsuit or otherwise) those copyrights in the Work. 6 | 7 | Dedicator recognizes that, once placed in the public domain, the Work may be freely reproduced, distributed, transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial, and in any way, including by methods that have not yet been invented or conceived. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bin2c - A simple utility for converting a binary file to a c application which 2 | can then be included within an application. 3 | 4 | Usage: 5 | 6 | ``` 7 | bin2c input_file output_file array_name 8 | ``` 9 | 10 | for example, using: 11 | ``` 12 | bin2c my_file.dat my_file.h data 13 | ``` 14 | 15 | will create something along the lines of 16 | 17 | ```c 18 | const char data[3432] = { 19 | 0x43, 0x28, 0x41, 0x11, 0xa3, 0xff, 20 | ... 21 | 0x00, 0xff, 0x23 22 | }; 23 | 24 | const int data_length = 3432; 25 | ``` 26 | 27 | This can then be used within your application, for example with SDL you would 28 | use SDL_RWops. The application can also be used in a very similar fashion to 29 | Qt's RC system. 30 | 31 | I haven't included a Makefile because the utility is SO simple, I don't 32 | think that one is needed. But for an example, compiling for GNU/Linux can be 33 | done as shown 34 | 35 | ``` 36 | gcc -o bin2c bin2c.c 37 | ``` 38 | 39 | In the current system, you can tell bin2c to compress the data with BZ2 40 | compression. This would be very useful in applications where a lot of files 41 | are stored this way or if memory is tight (although not CPU). To produce an 42 | executable which can make bz2 files, define USE_BZ2. However, since this is 43 | such a simple application, you can either define USE_BZ2 or not and it will 44 | then produce compressed data or not. An example as to how to compile a BZ2 45 | compression version of bin2c is as such 46 | 47 | ``` 48 | gcc -o bin2cbz2 bin2c.c -DUSE_BZ2 -lbz2 49 | ``` 50 | 51 | This will add an extra constant, data_length_uncompressed, which is the size 52 | of the file before it was compressed. So to decompress the file, you would 53 | do something like the following: 54 | 55 | ```c 56 | unsigned int decompressed_size = data_length_uncompressed; 57 | char *buf = malloc(data_length_uncompressed); 58 | int status; 59 | 60 | status = BZ2_bzBuffToBuffDecompress(buf, &decompressed_size, 61 | const_castdata, (unsigned int)data_length, 0, 0); 62 | 63 | // do something with buf 64 | free(buf); 65 | ``` 66 | 67 | I'm not entirely happy with having to do const_cast in C++ so if anyone can 68 | suggest an alternative then I'd be happy to implement it. 69 | 70 | Patches are welcome, just fork the project on github and send me a pull 71 | request. If you are unable or unwilling to do this through github, then feel 72 | free to email me your patch. This utility is so small I don't think that any 73 | licence is needed, and I took most of the code from Serge Fukanchick and made 74 | quite a few modifications so left it in the public domain. So please just send 75 | me a little note to say that you don't mind your code being in the public 76 | domain. 77 | -------------------------------------------------------------------------------- /bin2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is bin2c program, which allows you to convert binary file to 3 | * C language array, for use as embedded resource, for instance you can 4 | * embed graphics or audio file directly into your program. 5 | * This is public domain software, use it on your own risk. 6 | * Contact Serge Fukanchik at fuxx@mail.ru if you have any questions. 7 | * 8 | * Some modifications were made by Gwilym Kuiper (kuiper.gwilym@gmail.com) 9 | * I have decided not to change the licence. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef USE_BZ2 18 | #include 19 | #endif 20 | 21 | int 22 | main(int argc, char *argv[]) 23 | { 24 | char *buf; 25 | char *ident; 26 | unsigned int i, file_size, need_comma; 27 | 28 | FILE *f_input, *f_output; 29 | 30 | #ifdef USE_BZ2 31 | char *bz2_buf; 32 | unsigned int uncompressed_size, bz2_size; 33 | #endif 34 | 35 | if (argc < 4) { 36 | fprintf(stderr, "Usage: %s binary_file output_file array_name\n", 37 | argv[0]); 38 | return -1; 39 | } 40 | 41 | f_input = fopen(argv[1], "rb"); 42 | if (f_input == NULL) { 43 | fprintf(stderr, "%s: can't open %s for reading\n", argv[0], argv[1]); 44 | return -1; 45 | } 46 | 47 | // Get the file length 48 | fseek(f_input, 0, SEEK_END); 49 | file_size = ftell(f_input); 50 | fseek(f_input, 0, SEEK_SET); 51 | 52 | buf = (char *) malloc(file_size); 53 | assert(buf); 54 | 55 | fread(buf, file_size, 1, f_input); 56 | fclose(f_input); 57 | 58 | #ifdef USE_BZ2 59 | // allocate for bz2. 60 | bz2_size = 61 | (file_size + file_size / 100 + 1) + 600; // as per the documentation 62 | 63 | bz2_buf = (char *) malloc(bz2_size); 64 | assert(bz2_buf); 65 | 66 | // compress the data 67 | int status = 68 | BZ2_bzBuffToBuffCompress(bz2_buf, &bz2_size, buf, file_size, 9, 1, 0); 69 | 70 | if (status != BZ_OK) { 71 | fprintf(stderr, "Failed to compress data: error %i\n", status); 72 | return -1; 73 | } 74 | 75 | // and be very lazy 76 | free(buf); 77 | uncompressed_size = file_size; 78 | file_size = bz2_size; 79 | buf = bz2_buf; 80 | #endif 81 | 82 | f_output = fopen(argv[2], "w"); 83 | if (f_output == NULL) { 84 | fprintf(stderr, "%s: can't open %s for writing\n", argv[0], argv[2]); 85 | return -1; 86 | } 87 | 88 | ident = argv[3]; 89 | 90 | need_comma = 0; 91 | 92 | fprintf(f_output, "const char %s[%i] = {", ident, file_size); 93 | for (i = 0; i < file_size; ++i) { 94 | if (need_comma) 95 | fprintf(f_output, ", "); 96 | else 97 | need_comma = 1; 98 | if ((i % 11) == 0) 99 | fprintf(f_output, "\n\t"); 100 | fprintf(f_output, "0x%.2x", buf[i] & 0xff); 101 | } 102 | fprintf(f_output, "\n};\n\n"); 103 | 104 | fprintf(f_output, "const int %s_length = %i;\n", ident, file_size); 105 | 106 | #ifdef USE_BZ2 107 | fprintf(f_output, "const int %s_length_uncompressed = %i;\n", ident, 108 | uncompressed_size); 109 | #endif 110 | 111 | fclose(f_output); 112 | 113 | return 0; 114 | } 115 | --------------------------------------------------------------------------------