web-dev-qa-db-ja.com

ファイルを実行可能ファイルに埋め込む方法は?

C++で記述された小さなデモ実行可能ファイルがあり、実行する前に読み込まれる5kbのPNG画像1つだけに依存します。これは、作成したピクセルテキストに使用されます。この1つのファイルのため、1つの実行可能ファイルではなくZipアーカイブを提供する必要があります。これにより、ダウンロードと「再生」の間に十分な摩擦が生じ、試してみるのをやめさせると思います。

私の質問は、PNGファイル(および実際には他のファイル)を実行可能ファイルまたはソースコードに埋め込み、単一のファイルにして実行可能ファイルが使用できるようにすることですか?

PNGをバイトストリームとして解析する機能があるので、ピクセルデータに変換する必要はありません。

前もって感謝します! (これと同様のタイトルを持つ他の質問が存在しますが、それらとその回答はより具体的な問題に入るようであり、あまり役に立ちませんでした)

edit:コンパイラはVisual C++ 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);

};

最終編集ImageMagick これは、Alfも私が必要とすることを正確に実行してくれたことに感謝します。

25
Anne Quinn

移植可能な方法は、次のような関数を定義することです

typedef unsigned char Byte;

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

次に、PNGファイルをバイナリとして読み取り、C++中かっこ初期化子テキストを生成する小さなヘルパープログラムを作成するだけです。 Edit:@awoodlandが質問へのコメントで指摘しました ImageMagick にはこのような小さなヘルパープログラムがある…

もちろん、Windows固有のプログラムの場合は、代わりに通常のWindowsリソーススキームを使用してください。

乾杯&hth。、

10

XDを見てください。

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

最後に、xdはバイナリファイルを読み取り、ファイルからのデータを含むC言語のデータ宣言を発行できます。これは、Cプログラム内にバイナリデータを埋め込む場合に便利です。

個人的には、Windowsのリソースを使用しますが、実行可能形式の知識を必要としない真にポータブルな方法が必要な場合は、これが適しています。 PNG、JPG、その他...

10
Roddy

Base64 ファイルをエンコードして、コード内のどこかに文字列に入れます;)

7
fabrizioM

これは実行形式に依存します。つまり、本質的にオペレーティングシステム/コンパイラに依存します。 この質問 で述べたように、Windowsはこのためのリソースシステムを提供しています。

4
Puppy

プログラムリソースに任意のファイルを埋め込むことができます: (MSDN)User-Defined Resource

ユーザー定義のリソース定義ステートメントは、アプリケーション固有のデータを含むリソースを定義します。データの形式は任意で、特定のファイルのコンテンツ(filenameパラメーターが指定されている場合)または一連の数値と文字列(raw-dataブロックが指定されている場合)として定義できます。

nameID typeID filename

ファイル名は、リソースのバイナリデータを含むファイルの名前を指定します。ファイルの内容はリソースとして含まれています。 RCは、バイナリデータを解釈しません。データが適切にターゲットコンピュータアーキテクチャに合わせられるようにするのは、プログラマの責任です。

これが完了したら、 LoadResource関数 を使用して、ファイルに含まれるバイトにアクセスできます。

4
Mark Ransom

Linuxでは、これを使用します。これは、少し変更されていますが、いくつかの4kデモを実行しようとしたときに見つけたいくつかの例に基づいています。私はそれがウィンドウでも動作すると信じていますが、デフォルトのVSインラインアセンブリでは動作しません。私の回避策は、このコードまたは @ MarkRansom が示唆するWindowsリソースシステムのいずれかを使用するようにマクロを定義することです(動作するのはかなり苦痛ですが、最終的には動作します)。

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