34

I have a small demo executable wrote in C++ that depends only on one 5kb PNG image being loaded before it can run, which is used for a pixel text I made. Because of this one file, I would need to give out a ZIP archive instead of just one executable file, which creates enough friction between download and 'play' that I believe would dissuade some from trying it out.

My question is, is there anyway to embed the PNG file (and any other file really) into the Executable or source code so that it is a single file, and the executable can use it?

I have the ability to parse the PNG as a byte stream, so it does not need converted to pixel data.

Thanks in advance! (Other questions with a similar title to this exist, but they and their answers seem to get into more specific issues and weren't very helpful)

edit:The compiler is Visual C++ 2010 and this is on Windows (though I would want to avoid windows specific utilities for this)

edit2: Alf's answer seemed like the most portable method, so I quickly wrote a function to parse the PNG file into a TXT or header file that could be read as a unsigned char array. It appears to be identical in this form to the PNG file itself, but my png loader won't accept the array. When loading it from memory, the PNG parser takes a (void * buffer, size_t length) if it matters.

The code if you wanted to see, but I'll still accept other answers if you think they're better than this method:

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);

};

Final Edit: ImageMagick which Alf also mentioned did exactly what I needed of it, thanks!

phuclv
  • 37,963
  • 15
  • 156
  • 475
Anne Quinn
  • 12,609
  • 8
  • 54
  • 101
  • Possible duplicates: http://stackoverflow.com/questions/6005520/how-to-embed-resources-into-a-single-executable , http://stackoverflow.com/questions/4158900/embedding-resources-in-exe-using-gcc – Seth Carnegie Sep 02 '11 at 19:20
  • also: http://stackoverflow.com/questions/4864866/c-c-with-gcc-statically-add-resource-files-to-executable-library/4864879#4864879 – Flexo Sep 02 '11 at 19:21
  • 1
    Well, the simple (but not necessarily maintainable) way is to include it as an array. http://thedailywtf.com/Articles/The-cbitmap.aspx – Nick ODell Sep 02 '11 at 19:22
  • 1
    @Seth , awoodland - Before the close votes roll in, aha, those questions are solved by using linker options with GCC, which I don't use. – Anne Quinn Sep 02 '11 at 19:25
  • 3
    Doesn't VC++ support "resources"? (Granted this is VS-or-compatible specific...) –  Sep 02 '11 at 19:26
  • I didn't vote close but before the VC2010 edit they were strongly related. It's not really possible to solve this general problem in a portable way (other than saying "use QT" etc.) since executables are inherently non-portable though. The image magick one *is* portable though, but doesn't do it as a PNG file. – Flexo Sep 02 '11 at 19:29
  • @awoodland - sorry, I should have said that from the getgo, but I also thought there would be a portable method for this too... – Anne Quinn Sep 02 '11 at 19:32
  • the closest to portable is [using imagemagick](http://stackoverflow.com/questions/4864866/c-c-with-gcc-statically-add-resource-files-to-executable-library/4864879#4864879) (or similar tools) to make you a `static` byte array, but it's *not* PNG format. – Flexo Sep 02 '11 at 19:35
  • Your generating code puts in extra commas at every line end. I'd try fixing that (or using XD...) – Roddy Sep 02 '11 at 19:53
  • @Roddy - thanks, fixed it up, not sure where that came from. I'll ... probably just end up using a helper program for this anyway, aha. I seem to be missing some nuance when converting the file to a byte array – Anne Quinn Sep 02 '11 at 19:57
  • One other minor addition: at least for a/the Windows version, it's probably easier to use a BMP file instead PNG. If you already have the code written, it may be easiest to leave it alone, but if you're still writing the code, Windows has functions built in for loading and displaying BMP files. – Jerry Coffin Sep 02 '11 at 23:54
  • I wonder how Qt does it ? – bhathiya-perera Feb 09 '15 at 07:42
  • Possible duplicate of [Embedding resources in executable using GCC](https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc) – Ciro Santilli OurBigBook.com Nov 15 '18 at 15:59

9 Answers9

20

A portable way is to define a function like

typedef unsigned char Byte;

Byte const* pngFileData()
{
    static Byte const data =
    {
        // Byte data generated by a helper program.
    };
    return data;
}

Then all you have to do is to write a little helper program that reads the PNG file as binary and generates the C++ curly braces initializer text. Edit: @awoodland has pointed out in comment to the question, that ImageMagick has such a little helper program…

Of course, for a Windows-specific program, instead use the ordinary Windows resource scheme.

Cheers & hth.,

Community
  • 1
  • 1
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I speed wrote a parsing function to do this. It's still bugged a little, but it puts out the correct array it seems. Was this the general idea you had in mind? (I pasted the code into the question body) – Anne Quinn Sep 02 '11 at 19:48
  • Oh, there's programs that already do this? Didn't catch that edit, aha, might as well just use that instead! – Anne Quinn Sep 02 '11 at 19:55
  • If the file is too large (for my PC with VS2017 it is 3MB+), the IDE/editor will be slow after putting the data code into your code. – zwcloud Jul 08 '19 at 04:56
  • @zwcloud Yeah... I'm not surprised, somehow. Best keep this as a separate file and `include` it. – spacer GIF Jul 28 '19 at 12:06
  • 1
    actually `static Byte const data[]` – PinkTurtle Apr 14 '21 at 23:19
15

Look at XD:

http://www.fourmilab.ch/xd/

Finally, xd can read a binary file and emit a C language data declaration which contains the data from the file. This is handy when you wish to embed binary data within C programs.

Personally, I'd use resources for windows, but if you require a truly portable way that doesn't involve knowledge of the executable format, this is the way to go. PNG, JPG, whatever...

Roddy
  • 66,617
  • 42
  • 165
  • 277
  • 6
    xxd -i in almost any shell by default, often installed by vim packages. – kert Jan 01 '17 at 02:15
  • 1
    `xd` is also the name of a directory changing program of some sort. `xxd -i` works perfectly - from data.txt, the result contains null-terminated `unsigned char data_txt[]` and `unsigned int data_txt_len`; you can include it as-is, include it inside a namespace/struct/function, compile and link it in statically, etc. – John P Aug 04 '17 at 19:15
8

Base64 encode the file and put it in a string somewhere in your code ;)

fabrizioM
  • 46,639
  • 15
  • 102
  • 119
6

You can embed any arbitrary file into your program resources: (MSDN) User-Defined Resource.

A user-defined resource-definition statement defines a resource that contains application-specific data. The data can have any format and can be defined either as the content of a given file (if the filename parameter is given) or as a series of numbers and strings (if the raw-data block is specified).

nameID typeID filename

The filename specifies the name of a file containing the binary data of the resource. The contents of the file are included as the resource. RC does not interpret the binary data in any way. It is the programmer's responsibility to ensure that the data is properly aligned for the target computer architecture.

Once you've done that you can use the LoadResource function to access the bytes contained in the file.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
4

This is executable-format dependent, which means inherently operating system/compiler dependent. Windows offers the Resources system for this as mentioned in this question.

Community
  • 1
  • 1
Puppy
  • 144,682
  • 38
  • 256
  • 465
2

On linux I use this. It's based off a few examples I found when trying to do some 4k demos, albeit modified a bit. I believe it can work on windows too, but not with the default VS inline assembly. My workaround is #defining a macro to either use this code or the windows resource system that @MarkRansom suggests (quite painful to get working, but does work eventually).

//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
Community
  • 1
  • 1
jozxyqk
  • 16,424
  • 12
  • 91
  • 180
2

If I want to embed static data into an executable, I would package it into a .lib/.a file or a header file as an array of unsigned chars. That's if you are looking for a portable approach. I have created a command line tool that does both actually here. All you have to do is list files, and pick option -l64 to output a 64bit library file along with a header that includes all pointers to each data.

You can explore more options as well.for example, this option:

>BinPack image.png -j -hx

will output the data of image.png into a header file, as hexadecimal and lines will be justified per -j option.

const unsigned char BP_icon[] = { 
0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
0x00,0x00,0x01,0xed,0x00,0x00,0x01,0xed,0x08,0x06,0x00,0x00,0x00,0x34,0xb4,0x26,
0xfb,0x00,0x00,0x02,0xf1,0x7a,0x54,0x58,0x74,0x52,0x61,0x77,0x20,0x70,0x72,0x6f,
0x66,0x69,0x6c,0x65,0x20,0x74,0x79,0x70,0x65,0x20,0x65,0x78,0x69,0x66,0x00,0x00,
0x78,0xda,0xed,0x96,0x5d,0x92,0xe3,0x2a,0x0c,0x85,0xdf,0x59,0xc5,0x2c,0x01,0x49,
0x08,0x89,0xe5,0x60,0x7e,0xaa,0xee,0x0e,0xee,0xf2,0xef,0x01,0x3b,0x9e,0x4e,0xba,
0xbb,0x6a,0xa6,0x66,0x5e,0x6e,0x55,0x4c,0x8c,0x88,0x0c,0x07,0xd0,0x27,0x93,0x84,
0xf1,0xef,0x3f,0x33,0xfc,0xc0,0x45,0xc5,0x52,0x48,0x6a,0x9e,0x4b,0xce,0x11,0x57,
0x2a,0xa9,0x70,0x45,0xc3,0xe3,0x79,0xd5,0x5d,0x53,0x4c,0xbb,0xde,0xd7,0xe8,0x57,
0x8b,0x9e,0xfd,0xe1,0x7e,0xc0,0xb0,0x02,0x2b,0xe7,0x03,0xcf,0xa7,0xa5,0x87,0xff,
0x1a,0xf0,0xb0,0x54,0xd1,0xd2,0x0f,0x42,0xde,0xae,0x07,0xc7,0xf3,0x83,0x92,0x4e,
0xcb,0xfe,0x22,0xc4,0xa7,0x91,0xb5,0xa2,0xd5,0xee,0x97,0x50,0xb9,0x84,0x84,0xcf,
0x07,0x74,0x09,0xd4,0x73,0x5b,0x31,0x17,0xb7,0x8f,0x5b,0x38,0xc6,0x69,0xaf}
The Oathman
  • 125
  • 7
2

I'll mention #embed for completeness and hoping this will "soon" be a (standard) reality.

C23 (the C not C++ programming language) has already incorporated such a functionality as a language feature allowing you to write:


int main (int, char*[]) {
    static const char sound_signature[] = {
#embed <sdk/jump.wav>
// ^^^^^^^^^^^^^^^^^^
    };
    static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) >= 4,
        "There should be at least 4 elements in this array.");

    return 0;
}

For a C++ project, having a C subcomponent just for this use case might be a stretch, unless your application heavily requires embedding data in some way. My intuition is that implementations will "quietly" make this available to C++ even before it's in the standard. You can read more on the topic at the feature's author blog (where the above example was borrowed from).

Bear in mind that the exact same feature was being pursued even earlier for C++ but made it into the C standard first. A paper (for c++26 probably) is available here suggesting the following sytnax:

#include <embed>


constexpr std::span<const std::byte> 
  fxaa_binary = std::embed("fxaa.spirv");

i.e. avoiding the preprocessor altogether.

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
0

I came here looking for a bash script, so that I can generate the C array of bytes in a mostly-cross-platform compatible way (I depend on mingw bash for my windows builds anyway) without having to compile a helper tool or depend on any tools that don't come standard with a normal bash shell. Here's my take:

#!/bin/sh
set -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
OUT_FILE="$SCRIPT_DIR/src/alloverse_binary_schema.h"
BINARY_FILE="$SCRIPT_DIR/include/allonet/schema/alloverse.bfbs"
VAR_NAME="alloverse_schema"

echo "static const unsigned char ${VAR_NAME}_bytes[] = {" > "$OUT_FILE"
hexdump -ve '1/1 "0x%02x, "' "$BINARY_FILE" >> "$OUT_FILE"
echo "0x00}; static const int ${VAR_NAME}_size = sizeof(${VAR_NAME}_bytes); " >> "$OUT_FILE"

I can then just #include this from the C file where I use it, and use foo_bytes and foo_size as needed:

#include "alloverse_binary_schema.h"
bool allo_initialize(void)
{
    g_alloschema = reflection_Schema_as_root(alloverse_schema_bytes);
}

This script should be adaptable to your needs by adjusting OUT_FILE, BINARY_FILE and VAR_NAME (perhaps taking them as arguments to the script).

nevyn
  • 7,052
  • 3
  • 32
  • 43