Bin2C is a simple utility for converting a binary file to a C array declaration, which can then be included within an application.
Usage:
bin2c input_file [output_file] [options]
The input_file
parameter is required.
The name (and path) of the output_file
may be explicitly set. If not specified,
the output file has the same name as the input file, but with the extension .h
.
Various options are available:
Short | Long | Description |
---|---|---|
-a | --append | Append to the output file instead of overwriting it. |
-b number | --bits number | Set the width in bits of the array elements. This can be 8, 16 or 32 (for uint8_t , uint16_t or uint32_t respectively). The default bit size = 8. |
-d | --define | Declare the array size as a #define (default is to declare it as a "const unsigned int" variable). |
-h | --help | Show brief help. |
-l name | --label name | Set the symbol name for the array. If not specified, the symbol name is the input filename, without extension or path. However, if the filename is not a valid symbol name, this option must be used to set the symbol name explicitly. |
-m | --mutable | Declare the array as mutable (non-const). |
-t | --text | Open the input file as a text file (Microsoft Windows only; this esssentially translates CR-LF pairs in the input file to LF). |
-z | --zero | Append a zero terminator byte at the end of the array. |
For example, using:
bin2c my_file.dat --label data
will create a file called my_file.h
with contents along the lines of:
const uint8_t data[3432] = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23
};
const int data_length = 3432;
This can then be used within your application, for example with SDL you would use SDL_RWops. The application can also be used in a very similar fashion to Qt's RC system.
The purpose of the --zero
option is that it allows you to embed a text file
in a C program. Then, the generated array may be manipulated as a string (text
files do not have zero bytes). In Linux and Unix-like operating systems, lines
in a text files end with a "newline" (which is the LF character). In Microsoft
Windows, lines end with CR-LF pairs. The CR characters are redundant in the
generated array, in most cases. Therefore, you may have these stripped with the
--text
option.
For binary formats, the alignment may be important. A C/C++ compiler makes sure
that integers are aligned on a multiple of the integer size. Thus, a simple and
portable way to ensure that the generated array is 32-bit aligned, is to dump
the data as 32-bit integers. This is the purpose of the --bits
option. Note
that the multi-byte values are in Little Endian, so that the byte order is the
same as for byte-sized fields.
In the typical case where you embed binary data inside a C/C++ program, you will
use the data as-is. That is, you will not modify it. The default action of Bin2C,
to declare the array as "const" is what you want. As a side benefit, when the
code is for a microcontroller, the array will end up in Flash ROM, and not in
SRAM (and microcontrollers typically have more Flash memory than SRAM). However,
in some cases, you may want the data to be changeable by the code that you embed
it in. To this end, use the option --mutable
.
I haven't included a Makefile because the utility is so simple that I don't think that one is needed. But for an example, compiling for GNU/Linux can be done as shown
gcc -o bin2c bin2c.c
In the current system, you can tell bin2c to compress the data with BZ2 compression. This would be very useful in applications where a lot of files are stored this way or if memory is tight (although not CPU). To produce an executable which can make bz2 files, define USE_BZ2. However, since this is such a simple application, you can either define USE_BZ2 or not and it will then produce compressed data or not. An example as to how to compile a BZ2 compression version of bin2c is as such
gcc -o bin2cbz2 bin2c.c -DUSE_BZ2 -lbz2
This will add an extra constant, data_length_uncompressed, which is the size of the file before it was compressed. So to decompress the file, you would do something like the following:
unsigned int decompressed_size = data_length_uncompressed;
char *buf = malloc(data_length_uncompressed);
int status;
status = BZ2_bzBuffToBuffDecompress(buf, &decompressed_size,
const_cast<char *>data, (unsigned int)data_length, 0, 0);
// do something with buf
free(buf);
I'm not entirely happy with having to do const_cast in C++ so if anyone can suggest an alternative then I'd be happy to implement it.
Patches are welcome, just fork the project on github and send me a pull request. If you are unable or unwilling to do this through github, then feel free to email me your patch. This utility is so small I don't think that any licence is needed, and I took most of the code from Serge Fukanchick and made quite a few modifications so left it in the public domain. So please just send me a little note to say that you don't mind your code being in the public domain.