Как вставить файл в исполняемый файл?

У меня есть небольшой демонстрационный исполняемый файл, написанный на С++, который зависит только от одного загружаемого PNG-изображения размером 5 килобайт до его запуска, который используется для текста пикселя, который я сделал. Из-за этого одного файла мне нужно будет выдать ZIP-архив, а не только один исполняемый файл, что создает достаточное трение между загрузкой и "игрой", которые, как я считаю, будут отговаривать некоторых из них.

Мой вопрос в том, есть ли в любом случае встроить PNG файл (и любой другой файл) в исполняемый или исходный код, чтобы он был единственным файлом, и исполняемый файл может его использовать?

У меня есть возможность анализировать PNG как поток байтов, поэтому он не нуждается в преобразовании в данные пикселя.

Спасибо заранее! (Другие вопросы с похожим названием для этого существуют, но они и их ответы, похоже, затрагивают более конкретные проблемы и не очень помогают)

edit. Компилятор - это Visual С++ 2010, и это работает в Windows (хотя я бы хотел, чтобы для этого были использованы специальные утилиты для Windows)

edit2: ответ Alf казался самым переносимым методом, поэтому я быстро написал функцию для синтаксического анализа PNG файла в TXT или заголовочный файл, который можно было бы читать как массив unsigned char. Кажется, что он идентичен в этом виде самому файлу PNG, но мой загрузчик png не принимает массив. При загрузке из памяти парсер PNG принимает (void * buffer, size_t length), если это имеет значение.

Код, если вы хотите его увидеть, но я по-прежнему буду принимать другие ответы, если вы думаете, что они лучше этого метода:

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, о котором Alf также упомянул, именно то, что мне нужно, спасибо!

Ответы

Ответ 1

Портативный способ - определить функцию типа

typedef unsigned char Byte;

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

Тогда вам нужно только написать небольшую вспомогательную программу, которая читает PNG файл как двоичный файл и генерирует текст инициализатора фигурных скобок С++. Изменить: @awoodland указала в комментарии к вопросу, что ImageMagick имеет такую ​​небольшую вспомогательную программу & hellip;

Конечно, для программы, зависящей от Windows, вместо этого используйте обычную схему ресурсов Windows.

Приветствия и hth.,

Ответ 2

Посмотрите на XD:

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

Наконец, xd может читать двоичный файл и испускать данные языка C которое содержит данные из файла. Это удобно, когда вы хотите встроить двоичные данные в программы C.

Лично я использую ресурсы для окон, но если вам нужен действительно переносимый способ, который не включает знание исполняемого формата, это путь. PNG, JPG, что угодно...

Ответ 3

Это зависит от исполняемого файла, что означает зависящую от операционной системы/компилятора. Windows предлагает систему ресурсов для этого, как указано в этом вопросе.

Ответ 4

Base64 закодировать файл и поместить его в строку где-нибудь в вашем коде;)

Ответ 5

Вы можете вставлять любые произвольные файлы в свои программные ресурсы: (MSDN) Пользовательский ресурс.

Определяемый пользователем оператор определения ресурса определяет ресурс, содержащий данные, относящиеся к конкретным приложениям. Данные могут иметь любой формат и могут быть определены либо как содержимое данного файла (если указан параметр имени файла), либо как серия чисел и строк (если указан блок необработанных данных).

nameID typeID filename

Имя файла указывает имя файла, содержащего двоичные данные ресурса. Содержимое файла включено в качестве ресурса. RC не интерпретирует двоичные данные каким-либо образом. Обязанности программиста - обеспечить правильное выравнивание данных для целевой компьютерной архитектуры.

После этого вы можете использовать функцию LoadResource для доступа к байтам, содержащимся в файле.

Ответ 6

В linux я использую это. Это основано на нескольких примерах, которые я обнаружил при попытке сделать несколько демонстраций 4k, хотя и немного изменился. Я считаю, что он может работать и с окнами, но не с встроенной сборкой VS по умолчанию. Мое обходное решение #defining макроса для использования этого кода или системы ресурсов Windows, что @MarkRansom предлагает (довольно больно работать, но в конечном итоге работает).

//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