2017-02-16 21 views
0

私はビットマップを使ってVC++ 6でプロジェクトを持っています。私はプログラム的にいくつかのビットマップを抽出し、.bmpファイルとして保存したいと思います。.exeファイルから.bmpを抽出する

お願いします。

これはいくつかのステップです。

  1. 私はVC++ 6のプロジェクトでVC++のビットマップエディタで私が作ったビットマップをいくつか持っています。
  2. .exeのメニューをクリックします。
  3. プログラム自体からすべての.bmpファイルを抽出します(それが既に持っている)と.bmpの

事前に感謝 に関して

ulka

+1

外部実行可能ファイルリソースセクションからイメージを抽出しますか?または実行中のプログラムの独自のリソースから? –

+0

バイナリからLoadResource、FindResourceなどのメソッドがあります。 https://www.codeproject.com/Articles/4221/Adding-and-extracting-binary-resourcesを参照してください。 – sameerkn

+0

[あなたがこれまでに試したこと](http://whathaveyoutried.com)を表示するようあなたの質問を編集してください。問題のあるコードの[mcve]を含める必要があります。次に、特定の問題を解決するために役立つことができます。 [ask]も読んでください。 –

答えて

4

ビットマップリソースとしてハードディスクに保存しますBITMAPFILEHEADERを取り除いたビットマップファイルだけです。 も参照してください:https://blogs.msdn.microsoft.com/oldnewthing/20091211-00/?p=15693

あなたがする必要があるのは、このヘッダーを自分で作成してファイルに書き込むことです。最も一般的な24 bppビットマップは比較的簡単ですが、他のビット深度もサポートしたい場合は少し複雑です。

次に、FindResource()/ LoadResource()/ LockResource()呼び出しで取得したデータを書き込みます。

コード例(1 BPP、4 BPP、8 BPP、および24のBPPビットマップでテスト):

int main() 
{ 
    // Obtain a handle to the current executable 
    HMODULE hInst = ::GetModuleHandle(nullptr); 

    // Locate and load a bitmap resource of the executable 
    if(HRSRC hr = ::FindResource(hInst, MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP)) 
     if(HGLOBAL hg = ::LoadResource(hInst, hr)) 
      if(auto pData = reinterpret_cast<const char*>(::LockResource(hg))) 
      { 
       DWORD resourceSize = ::SizeofResource(hInst, hr); 

       // Check if we safely read the complete BITMAPINFOHEADER 
       // (to prevent a GPF in case the resource data is corrupt). 
       if(resourceSize >= sizeof(BITMAPINFOHEADER)) 
       { 
        auto& bmih = reinterpret_cast<const BITMAPINFOHEADER&>(*pData); 

        // For simplicitly we can only save uncompressed bitmaps. 
        if(bmih.biCompression == BI_RGB) 
        { 
         // Calculate the size of the bitmap pixels in bytes. 
         // We use this to calculate BITMAPFILEHEADER::bfOffBits correctly. 
         // This is much easier than calculating the size of the color table. 
         DWORD widthBytes = (bmih.biBitCount * bmih.biWidth + 31)/32 * 4; 
         DWORD heightAbs = abs(bmih.biHeight); // height can be negative for a top-down bitmap! 
         DWORD pixelSizeBytes = widthBytes * heightAbs; 

         // Create the bitmap file header. 
         BITMAPFILEHEADER bfh = { 0 }; 
         bfh.bfType = 0x4D42;       // magic bytes: "BM" 
         bfh.bfSize = sizeof(bfh) + resourceSize; // total file size 
         bfh.bfOffBits = bfh.bfSize - pixelSizeBytes; // offset to bitmap pixels 

         // Write file header and bitmap resource data to file. 
         std::ofstream of("mybitmap1.bmp", std::ios::binary); 
         of.write(reinterpret_cast<const char*>(&bfh), sizeof(bfh)); 
         of.write(pData, resourceSize); 
        } 
       } 
      } 

    return 0; 
} 

を編集:

私のオリジナルの答えはこと、(文字通り)という重要なビットを逃しofstreamコンストラクタのフラグはios::binaryです。だからこそ、Arthur Gのコードはうまくいきませんでした。

なぜ、それは実際に私の旗がなくてもうまくいったのですか?面白いのは、私のテストビットマップが10の値を持つバイトを持っていなかったからです(プログラマーが自分のコードをテストすることを信じることはありません)!

デフォルトで起こることの1つは、行末がプラットフォームのデフォルトに応じて変換されることです。つまり、 '\ n'(ASCIIコード= 10)はWindowsプラットフォームでは「\ r \ n」に変換されます。もちろん、実際のビットマップはこの値をどこかに含んでいる可能性があるため、これはビットマップデータを完全に混乱させます。

私たちは、われわれのデータにはios :: binaryフラグとまったく同じようなデータを混乱させるべきではないことを明示的に伝える必要があります。

編集2:

楽しみのためだけに私もピクセルビットマップにつき1ビット、4ビット、8ビットで正しく動作するように私の例を拡張しました。 これらのビット深度では、BITMAPINFOHEADERの直後にピクセル配列が開始されないため、これはもう少し複雑です。ピクセル配列がカラーテーブルに来る前に、そのサイズはBITMAPFILEHEADER::bfOffBitsに加算されなければならない。

MSDNによれば、ビット深度が16以上であってもオプションのカラーテーブル(「システムカラーパレットのパフォーマンスを最適化する」という意味)が存在するため、さらに複雑になります。 (「biClrUsed」の下)

https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspxを見るので、代わりの方法と、カラーテーブルを使用する場合、私は単純に合計から画素アレイのサイズを減算することによりBITMAPFILEHEADER::bfOffBitsを計算し、すべてのダーティ詳細周り頭を包みますリソースサイズ(これは既に知られている)。

ピクセル配列のサイズを計算するのはかなり簡単ですが、バイト単位の幅は4の倍数(1 DWORD)に切り上げるように注意する必要があります。バイト単位でその幅が4

ボーナスの倍数でないビットマップを保存するときにそうしないと、エラーが発生します読ん

ウィキペディアの素敵なダイアグラムとビットマップファイル形式のかなり詳細な記述があります構造: https://en.wikipedia.org/wiki/BMP_file_format

関連する問題