インデックス ビットマップ生成、C++ 読み取りおよび書き込みプロセス

インデックス付きビットマップは、一般的な 16、24、32 ビット カラーの BMP 形式とは異なり、パレット + 8 ビット カラーを使用するビットマップ形式で、各ピクセルは 1 バイトのみを占有し、ピクセル値は 0 ~ 255 インデックスです。色はパレットの対応する位置データに保存されます

Photoshop でインデックス付きビットマップを作成する

Photoshop を使用して既存の画像を開き、メニュー [イメージ]、[モード]、[インデックス カラー...] を選択します。次に、
ポップアップ ダイアログ ボックスで、対応するアルゴリズムを選択してインデックス カラーをソートし、現在の画像の色を 256 色のいずれかにまとめます. 途中で確認すると、
ここに画像の説明を挿入画像はインデックス ビットマップになります. メニューの [画像]、[モード]、[カラー テーブル...] を再度使用すると、色を変更できます。パレットの内容を選択し、[名前を付けて保存...]を選択して、
ここに画像の説明を挿入8ビットカラーのBMP画像形式で保存します

GIMP はインデックス付きビットマップを作成します

メニュー【画像】、【モード】、【インデックス...】を介して、
ポップアップダイアログボックスは画像をインデックスカラーに変換し、
ここに画像の説明を挿入
メニュー【ウィンドウ】、【ドッキング可能ダイアログボックス】、【カラーテーブル】を介して】
色面パネルを開くと、次の操作で使用できます 操作で色とインデックス値を指定します 編集後
ここに画像の説明を挿入
、メニュー [ファイル]、[エクスポート...] から Windows BMP イメージを選択する必要があります。 ]、および8ビットのインデックスビットマップを生成できます

ビュー インデックス ビットマップとカラー テーブルを想像してください

Imagine は、さまざまな画像形式を簡単に表示できる軽量な無料の画像ブラウザです。公式サイト: https://www.nyam.pe.kr/dev/imagine/
インデックス ビットマップを開くと、【編集パレット】ここに画像の説明を挿入パレットウィンドウを開くボタン
ここに画像の説明を挿入

インデックス付きビットマップ ファイル形式

msdn ドキュメントを参照してください: https://docs.microsoft.com/zh-cn/windows/win32/gdi/bitmap-storage、ビットマップのストレージ形式が
ここに画像の説明を挿入

BITMAPFILEHEADER フォーマット

ヘッダー ファイル Wingdi.h で宣言

メンバー 例証する
bfType BM を示す 0x4D42
bfサイズ BITMAPFILEHEADER サイズを含むファイルの合計サイズ
bf予約済み1 0
bf予約済み2 0
bfOffBits ファイル ヘッダーに対する画像データ (カラー インデックス配列) の開始位置

BITMAPINFOHEADER 形式

ヘッダー ファイル Wingdi.h で宣言

メンバー 例証する
バイサイズ 構造体 BITMAPINFOHEADER のサイズは 40 です
画像幅
バイハイト 画像の高さ
複葉機 1
biBitCount インデックス ビットマップは 8
双方向圧縮 BI_RGB は非圧縮を意味します
biSizeImage 画像データのサイズ、通常はピッチ x biHeight、
ピッチは: biWidth * sizeof(pixel) の 4 バイト アライン バージョン
biXPelsPerMeter ピクセル/メートル
biYPelsPerMeter ピクセル/メートル
biClr使用済み インデックス ビットマップは 0 で、パレットに 256 色があることを示します。
biClr重要 0

C++ でインデックス ビットマップを読み取る

ビットマップを 2 次元配列 boost::multi_array<byte, 2> img に読み込む必要があるとします。

std::ifstream ifs("aaa.bmp", std::ios::binary);

//-		bfh	{bfType=19778 bfSize=787512 bfReserved1=0 ...}	tagBITMAPFILEHEADER
//		bfType	19778	unsigned short
//		bfSize	787512	unsigned long
//		bfReserved1	0	unsigned short
//		bfReserved2	0	unsigned short
//		bfOffBits	1078	unsigned long
BITMAPFILEHEADER bfh;
ifs.read((char*)&bfh, sizeof(bfh));
if (bfh.bfType != 0x4D42)
	return;

//-		bih	{biSize=40 biWidth=1024 biHeight=768 ...}	tagBITMAPINFOHEADER
//		biSize	40	unsigned long
//		biWidth	1024	long
//		biHeight	768	long
//		biPlanes	1	unsigned short
//		biBitCount	8	unsigned short
//		biCompression	0	unsigned long
//		biSizeImage	786434	unsigned long
//		biXPelsPerMeter	11808	long
//		biYPelsPerMeter	11808	long
//		biClrUsed	0	unsigned long
//		biClrImportant	0	unsigned long
BITMAPINFOHEADER bih;
ifs.read((char*)&bih, sizeof(bih));
if (bih.biCompression != BI_RGB || bih.biBitCount != 8)
	return;

// 位图每一行的数据字节长度是4的倍数
int pitch = (bih.biWidth * bih.biBitCount + 31) / 32 * 4;

// 逐行将数据读入二维数组
boost::multi_array<unsigned char, 2> img(boost::extents[bih.biHeight][bih.biWidth]);
for (int i = 0; i < bih.biHeight; i++)
{
    
    
	// Windows位图数据从下往上存储,所以需要反着读取
	long offset = bfh.bfOffBits + (bih.biHeight - i - 1) * pitch;
	ifs.seekg(offset, SEEK_SET);

	ifs.read((char*)&img[i][0], bih.biWidth * sizeof(unsigned char));
}

C++ でインデックス ビットマップを書き込む

先にビットマップの bfh と bih を読み込んだ後、データは既にメモリに表示されているので、同じパターンに従って、データをファイルに書き戻しますが、ビットマップ幅のデータは 4 の倍数が必要なため、それに応じて元の配列を拡張して保存することをお勧めします

// boost::multi_array<unsigned char, 2> img(...);
// 需要将二维数组img的宽度扩大到4的倍数
img.resize(boost::extents[img.shape()[0]][boost::alignment::align_up(img.shape()[1], 4)]);

std::ofstream ofs(path, std::ios::binary, _SH_DENYRW);

BITMAPFILEHEADER bfh = {
    
     0 };
BITMAPINFOHEADER bih = {
    
     0 };
bfh.bfType = 0x4D42;
bfh.bfOffBits = sizeof(bfh) + sizeof(bih) + sizeof(RGBQUAD) * 256;
bfh.bfSize = bfh.bfOffBits + img.num_elements() * sizeof(unsigned char);
bih.biSize = sizeof(bih);
bih.biWidth = img.shape()[1];
bih.biHeight = img.shape()[0];
bih.biPlanes = 1;
bih.biBitCount = 8;
bih.biCompression = BI_RGB;
bih.biSizeImage = img.num_elements() * sizeof(unsigned char);
bih.biXPelsPerMeter = 11808;
bih.biYPelsPerMeter = 11808;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

ofs.write((char*)&bfh, sizeof(bfh));
ofs.write((char*)&bih, sizeof(bih));

// 这里写入灰度数据到调色板数据,可在Photoshop面板中更改
for (int p = 0; p < 256; p++)
{
    
    
	RGBQUAD q = {
    
     p, p, p, 0 };
	ofs.write((char*)&q, sizeof(q));
}

for (int i = 0; i < img.shape()[0]; i++)
{
    
    
	ofs.write((char*)&img[img.shape()[0] - i - 1][0], img.shape()[1] * sizeof(unsigned char));
}

参考:
https://docs.microsoft.com/zh-cn/windows/win32/gdi/bitmap-storage
https://blog.csdn.net/Wintalen/article/details/1014820
https://sunriver2000.blog.csdn.net/article/details/104251831

おすすめ

転載: blog.csdn.net/tangyin025/article/details/126175940