インデックス付きビットマップは、一般的な 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