野暮の用事で。
ポイントはこんなとこ。
- Windows.hに定義されとるBITMAPFILEHEADER構造体とBITMAPINFOHEADER構造体を使う
- 構造体を含めてバイナリ形式で順番にファイルを作成する
- BITMAPFILEHEADER構造体とBITMAPINFOHEADER構造体はファイルの先頭で出力する
- 1ピクセルはRGBの3つとアルファチャンネル1つの計4バイト(8×3+8の計32)で表現する
んで、ビットマップを作るメソッドはこんな感じ。
//
// ヘッダーのインクルードをする
// ※mainメソッドでも共通で使う
//
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <Windows.h>
using namespace std;
/////////////////////////////////////////////////////////////////////
//
// ビットマップファイルを作成する
//
// @parameter filepath ファイルパス
// @parameter width 画像の幅(ピクセル)
// @parameter height 画像の高さ(ピクセル)
// @parameter pixel 画像情報(32ビット)
//
/////////////////////////////////////////////////////////////////////
void CreateBitmap(const string &filepath, const int width, const int height, const vector<unsigned char>& pixels)
{
//
// 変数を定義する
//
ofstream writer;
int bitcount = 8 * 3 + 8; // RGB×8bit+アルファ値で32
//
// ビットマップを作成する
//
try
{
// ローカル変数を定義する
int count = (width * height * (bitcount / 8)); // ピクセル数(4バイト×画素数)
int filesize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + count;
// ビットマップヘッダーを定義する
BITMAPINFOHEADER infoheader;
::memset(&infoheader, 0, sizeof(BITMAPINFOHEADER));
infoheader.biSize = sizeof(BITMAPINFOHEADER);
infoheader.biWidth = width;
infoheader.biHeight = height;
infoheader.biPlanes = 1;
infoheader.biBitCount = bitcount;
infoheader.biCompression = BI_RGB;
infoheader.biSizeImage = (width * height * (bitcount / 8));
infoheader.biXPelsPerMeter = 0;
infoheader.biYPelsPerMeter = 0;
infoheader.biClrUsed = 0;
infoheader.biClrImportant = 0;
// ファイルヘッダーを定義する
BITMAPFILEHEADER fileheader;
::memset(&fileheader, 0, sizeof(BITMAPFILEHEADER));
fileheader.bfType = ('M' << 8) | 'B';
fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + infoheader.biSizeImage;
fileheader.bfReserved1 = 0;
fileheader.bfReserved2 = 0;
fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// ファイルを開く
writer = ofstream(filepath, ios::out | ios::trunc | ios::binary);
if (!writer.is_open())
{
throw new exception("ファイルの作成に失敗しました...");
}
// 画像を書き込む
writer.write((char*)&fileheader, sizeof(BITMAPFILEHEADER));
writer.write((char*)&infoheader, sizeof(BITMAPINFOHEADER));
writer.write((const char*)&pixels[0], pixels.size());
}
catch (const exception & ex)
{
// エラー情報を出力する
cout << ex.what() << endl;
// ファイルを閉じる
if (writer.is_open())
{
writer.close();
}
throw ex;
}
// ファイルを閉じる
if (writer.is_open())
{
writer.close();
}
}
テスト用としてmain関数はこんな感じ。
/////////////////////////////////////////////////////////////////////
//
// エントリーポイント
//
/////////////////////////////////////////////////////////////////////
int main()
{
// 変数を定義する
string filepath = "C:\\Users\\tetsuyanbo\\Documents\\Work\\sample.bmp";
int width = 200; // 画像の幅
int height = 100; // 画像の高さ
int bitcount = 32; // チャンネル数
int size = (width * height * (bitcount / 8)); // 画素数
vector<unsigned char> pixels(size); // 画像情報のリスト
// ビットマップを作成する
CreateBitmap(filepath, width, height, pixels);
}
実行してみると…、ファイルは出来とる。
ファイルを開いてみたら、こんな感じ。
んまま、明日への自分へのメモってことで。

