2

32bppビットマップを作成する完全に機能するコードがあり、8bppビットマップが作成されるように変更する必要があります。

32bppビットマップを作成し、それに描画してから、ビットマップファイルを作成し、それをバイトのベクトルに格納するコードを次に示します。

// prepare bitmap:
BYTE* bitmap_data = NULL;
HDC hDC = GetDC(NULL);
HDC memHDC = CreateCompatibleDC(hDC);
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = desiredWidth;                 // desiredWidth is 800
bmi.bmiHeader.biHeight = desiredHeight;               // desiredHeight is 202
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = (((desiredWidth * bmi.bmiHeader.biBitCount + 31) & ~31) >> 3) * desiredHeight;
HBITMAP bitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&bitmap_data, NULL, NULL);
ReleaseDC(NULL, hDC);
DeleteDC(hDC);

... // drawing into bitmap

// prepare bitmap file header:
BITMAPFILEHEADER bf;
memset(&bf, 0, sizeof(BITMAPFILEHEADER));
bf.bfType = MAKEWORD('B', 'M');
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize;
bf.bfSize = bf.bfOffBits + bmi.bmiHeader.biSizeImage;

// write bitmap file into the vector:
std::vector<BYTE> bitmapData;
bitmapData.insert(bitmapData.end(), (BYTE*)&bf, ((BYTE*)&bf) + sizeof(BITMAPFILEHEADER));
bitmapData.insert(bitmapData.end(), (BYTE*)&bmi.bmiHeader, ((BYTE*)&bmi.bmiHeader) + sizeof(BITMAPINFOHEADER));
bitmapData.insert(bitmapData.end(), bitmap_data, bitmap_data + bmi.bmiHeader.biSizeImage);

その後、ベクトルはファイルに保存されます。

std::ofstream of("picture.bmp", std::ofstream::out | std::ofstream::binary);
of.write((char*)&bitmapData[0], bitmapData.size());
of.close();

出力画像は次のとおりです。

32bpp画像

私が試したこと:

最初のステップは、当然、この行でに置き換え32られました。これにより、画像が灰色で塗りつぶされました。次に、この回答に基づいて、次の変更を行いました。8bmi.bmiHeader.biBitCount = 32;

BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));

に変更されました:

struct BITMAPINFO256 {
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD bmiColors[256];
} bmi;
memset(&bmi, 0, sizeof(BITMAPINFO256));

呼び出される直前にこのループを追加しましたCreateDIBSection

for (UINT i = 0; i < 256; i++) {
    bmi.bmiColors[i].rgbRed   = i;
    bmi.bmiColors[i].rgbGreen = i;
    bmi.bmiColors[i].rgbBlue  = i;
}

bmi.bmiHeaderベクトルに書き込まれると、RGBQUAD配列が含まれますsizeof(BITMAPINFO256)。つまり、ヘッダーのサイズを表します。

新しいコード(ここでは完全なコード)は次の出力を生成します:

8bpp画像

新しい画像がそのように見えるのはなぜですか?そこで何が起こっているのですか?私は何が欠けていますか?

どんな助けでもありがたいです。

4

3 に答える 3

3

位置合わせの問題のようです。BITMAPFILEHEADERのbfOffBitsを更新して、ピクセルデータの最初のバイトを指すようにしてください。(変更しない場合は、おそらくパレットの先頭を指しています。)

つまり、sizeof(RGBQUAD)*256ここにも追加する必要があります。

bf.bfOffBits = sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize;

また、最初のスキャンラインがDWORD境界で開始することを確認してください。つまり、ファイルの先頭からのオフセットは4バイトの倍数である必要があります。同様に、各スキャンラインは4バイトの倍数にパディングする必要があります。(幅が偶数の場合、これらの問題は発生しない可能性があります。テストケースの中に奇数幅の画像があると便利です。)

于 2013-02-13T17:54:41.177 に答える
0

画像のパレットを生成する必要があります。32ビット画像の各ピクセルは、アルファ、赤、緑、青の8ビットとして保存されます。8ビット画像の場合と同様に、各ピクセルの値はパレットへの8ビットインデックスです。

あなたのfor(i = 0..255){bmi.bmiColors [i] .rgbRed = i; ....}コードはグレースケールパレットで生成されます。

画像全体が灰色で表示される場合は、位置合わせエラーのように聞こえます。メモリから、パレット化された画像の幅は4の倍数である必要があります。

ペイントから小さな256色(別名8ビット画像)を保存して、16進エディタで比較してみてください。

于 2013-02-13T18:03:03.433 に答える
0

添付したパレットのサイズを指定する必要があります。現在はゼロなので、パレットは画像の最初のピクセルの束として表示されます。

bmi.bmiHeader.biClrUsed = 256;
于 2013-02-13T17:41:04.953 に答える