5

BMP 形式の意味がわかりません。単純であることはわかっていますが、どういうわけか何かが欠けています。イメージを定義する実際のバイトが続く 2 つのヘッダーだと思っていましたが、数値が加算されません。

たとえば、この BMP ファイルをメモリ (640x480 8bpp グレースケール) にロードして、別のファイルに書き戻そうとしています。私が理解していることから、2 つの異なるヘッダー BITMAPFILEHEADER と BITMAPINFOHEADER があります。BITMAPFILEHEADER は 14 バイトで、BITMAPINFOHEADER は 40 バイトです (これは BMP に依存します。それは別の話です)。とにかく、BITMAPFILEHEADER は、そのパラメーター bfOffBits を介して、ビットマップ ビットがオフセット 1078 から始まることを示しています。これは、1024 ( 1078 - (40+14) ) バイトがあり、より多くの情報を運ぶことを意味します。それらのバイトは何ですか、どうすればそれらを読むことができますか、これが問題です。または、BMP をロードしてディスクに書き込むより正しい方法はありますか?

参考までに、私が使用したコードは次のとおりです(私はこれをすべてWindowsで行っています)。

#include <windows.h>
#include <iostream>
#include <stdio.h>


HANDLE hfile;
DWORD written;

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;

int main()
    hfile = CreateFile("image.bmp",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
ReadFile(hfile,&bfh,sizeof(bfh),&written,NULL);

ReadFile(hfile,&bih,sizeof(bih),&written,NULL);

int imagesize = bih.biWidth * bih.biHeight;

image = (unsigned char*) malloc(imagesize);

ReadFile(hfile,image,imagesize*sizeof(char),&written,NULL);

CloseHandle(hfile);

次に、ファイルへの書き込みとは正反対のことをしています。

hfile = CreateFile("imageout.bmp",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

WriteFile(hfile,&bfh,sizeof(bfh),&written,NULL);
WriteFile(hfile,&bih,sizeof(bih),&written,NULL);
WriteFile(hfile,image,imagesize*sizeof(char),&written,NULL);

CloseHandle(hfile);

編集 --- 解決済み

わかりましたので、ようやく正しく理解できました。結局のところ、それほど複雑ではありませんでした。Viktor が指摘したように、これらの 1024 バイトはカラー パレットを表します。

コードに次を追加しました。

RGBQUAD palette[256];
// [...] previous declarations [...] int main() [...] then read two headers
ReadFile(hfile,palette,sizeof(palette),&written,NULL);

そして、私が書き戻すとき、私は以下を追加しました、

WriteFile(hfile,palette,sizeof(palette),&written,NULL);
4

2 に答える 2

7

「それらのバイトは何ですか、どうすれば読み取ることができますか。これが問題です。」

Retired Ninja がコメントで述べたように、これらのバイトは Palette (または .BMP 形式の用語では ColorTable) です。基本的には、ビットマップ データで検出された各 8bpp 値に使用する色を指定するテーブルです。

グレースケールの場合、パレットは簡単です (カラー モデルと RGB -> グレースケール変換について話しているわけではありません)。

for(int i = 0 ; i < 256 ; i++)
{
    Palette[i].R = i;
    Palette[i].G = i;
    Palette[i].B = i;
}

ただし、ColorTable のエントリにはパディングが含まれているため、必要な 256 * 3 バイトではなく、4 * 256 バイトが必要です。ColorTable のエントリ (RGBQUAD Struct) の 4 番目のコンポーネントは「アルファ チャネル」ではなく、単に「予約済み」のものです。RGBQUAD の MSDN ( MSDN, RGBQUAD ) を参照してください。

詳細な形式の説明は、ウィキペディアのページにあります: Wiki, bmp format

RGBQUAD 構造を持つ SO に関するこのリンクされた質問もあります。

于 2012-05-29T08:30:57.533 に答える
2

Viktor が回答で述べているように、これらのビットはパレットです。それらの読み方については、このヘッダーのみのビットマップ クラスをご覧ください。特に、ColorTable指定された BMP のタイプに応じてパレット ビットをどのように扱うかについては、 への参照を参照してください。

于 2012-05-29T10:58:08.677 に答える