0

私はC++でビットマップデータを操作するのは非常に初めてで、問題があります。私はウィキペディアからこの例に従おうとしています。これが私が使用しているコードです:

#include <iostream>
#include <fstream>
#include <Windows.h>

using namespace std;

int main()
{

    //fileheader
    BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
    bf->bfType = 66;
    bf->bfSize = 70;
    bf->bfOffBits = 54;

    //infoheader
    BITMAPINFOHEADER* bi = new BITMAPINFOHEADER;
    bi->biSize = 40;
    bi->biWidth = 2;
    bi->biHeight = 2;
    bi->biPlanes = 1;
    bi->biBitCount = 24;
    bi->biCompression = 0;
    bi->biSizeImage = 16;
    bi->biXPelsPerMeter = 2835;
    bi->biYPelsPerMeter = 2835;
    bi->biClrUsed = 0;
    bi->biClrImportant = 0;

    //image data
    unsigned char* thedata = new unsigned char;
    thedata[0] = 0;
    thedata[1] = 0;
    thedata[2] = 255;

    thedata[3] = 255;
    thedata[4] = 255;
    thedata[5] = 255;

    thedata[6] = 0;
    thedata[7] = 0;

    thedata[8] = 255;
    thedata[9] = 0;
    thedata[10] = 0;

    thedata[11] = 0;
    thedata[12] = 255;
    thedata[13] = 0;

    thedata[14] = 0;
    thedata[15] = 0;

    //dc
    HDC dc = GetDC(NULL);

    //bitmap info
    BITMAPINFO* bmi = (BITMAPINFO*)bi;

    //handle to bitmap
    HBITMAP hbmp = CreateDIBitmap(dc, bi, CBM_INIT, thedata, bmi, DIB_RGB_COLORS);

    //output to bmp....?
    ofstream outFile;
    outFile.open("outtestbmp.bmp");
    outFile << hbmp;
    outFile.close();

}

私はこれを成し遂げる方法を見つけようとして過去数日間グーグルを検索してきました、しかし私はまだそれを機能させることができないようです。

これはエラーなしで準拠しますが、最後のouttestbmp.bmpファイルは開くことができません。これが機能するのを妨げている大きな間違い(おそらく数十)はありますか?(ofstreamを使用してbmpデータを出力するのは間違っているのではないかと疑っています)。

編集:bftypeを66に設定するのは間違っていると言われました。正しい値は何ですか?

また、出力の内容を示す.bmpファイルを作成しました。そのbmpの16進データは次のとおりです。

42 4D 46 00 00 00 00 00 00 00 36 00 00 00 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18        
00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF  
FF FF 00 00 FF 00 00 00 FF 00 00 00

そして、これが私が出力している私の.bmpのデータです:

42 00 46 00 00 00 CD CD CD CD 36 00 00 00 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18 
00 00 00 00 00 10 00 00 00 13 0B 00 00 13 0B 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 
FF FF 00 00 FF 00 00 00 FF 00 00 00
4

4 に答える 4

3
bf->bfType == 66;

これは2つの点で間違っています。第一に、それは間違った値であり(魔法の値は、リトルエンディアンのマシンではバイト「BM」または0x4d42です)、第二に、それは割り当てではありません。

それで:

unsigned char* thedata = new unsigned char;

1文字だけを割り当てますか?

この:

outFile << hbmp;

あなたが思っていることをしません。ハンドルを書いているだけです。ビットマップを作成する必要はありませんでした。初期化したデータ構造を書き出すだけです(正しく設定したら)。

そして、なぜあなたはすべてを新しくしているのですか?このようなものを動的に割り当てる必要はありません(また、削除する必要もありません)。

私は一般的に次のようなことをします(簡潔にするためにいくつかのコードが削除されています):

BITMAPFILEHEADER bf;
bf.bfType = 0x4d42;
bf.bfSize = 70;
bf.bfOffBits = 54;

//infoheader
BITMAPINFOHEADER bi;
bi.biSize = 40;
bi.biWidth = 2;
etc...

//image data
unsigned char* thedata = new unsigned char[16]; // Should really calculate this properly
thedata[0] = 0;
....

//output to bmp....?
ofstream outFile;
outFile.open("outtestbmp.bmp");
outFile.write((char *)&bf,sizeof(bf));
outFile.write((char *)&bi,sizeof(bi));
outFile.write((char *)thedata, 16);
outFile.close();
于 2013-02-01T16:26:06.457 に答える
1

まず、すべてのピクセルに十分なメモリを割り当てていません。次のようなものにする必要があります。

unsigned char* thedata = new unsigned char[numPixels * bytesPerPixel];

あなたの場合、2画像ごと224 bpp(ピクセルあたりのビット数)を使用して、12バイトを割り当てる必要があります。

各ピクセルはredgreenおよびblueチャネルの3バイトに対応します。

注:Windowのビットマップ作成プロセスを使用したことはありませんが、多くのライブラリを使用して、、などの画像を操作しましFreeImageSDLGD

于 2013-02-01T16:24:28.203 に答える
1

HBITMAP は、実際のビットマップではなく、ビットマップへのハンドルです。実際のビットマップはカーネル メモリに格納されます。ビットマップをファイルに書き込むだけの場合は、GDI を呼び出す必要はありません。それが実際のビットマップであったとしても、ディスク上と同じようにメモリに格納されていないため、実際にメモリ構造をファイルに書き込むには演算子のオーバーロードが必要です。

必要なのは、BITMAPFILEHEADER をファイルに書き込んでから、BITMAPINFOHEADER をファイルに書き込んでから、データを書き込むことだけです (RGB について話している場合は、インデックスなし)。

ビットマップが実際にどのようにディスクに保存されるかについての詳細は、次のとおりです。

ビットマップ ストレージ (MSDN)

ファイルからビットマップを読み取るのも同じです。

于 2013-02-01T16:30:09.433 に答える
0

まず、ピクセルに十分なデータを割り当てる必要があります。

unsigned char* thedata = new unsigned char[2 * 2 * 3];

write次に、ファイルを として使用して開く必要がありますbinary

それ以外の:

outFile.open("outtestbmp.bmp");
outFile << hbmp;

何かのようなもの:

outFile.open("outtestbmp.bmp", ios::binary||ios::out);

outfile.write(reinterpret_cast<char *>(bf), sizeof(BITMAPFILEHEADER));
outfile.write(reinterpret_cast<char *>(bi), sizeof(BITMAPINFOHEADER));
outfile.write(reinterpret_cast<char *>(thedata), 2 * 2 * 3); 

outfile.close();
于 2013-02-01T16:30:30.060 に答える