野暮の用事で。
ポイントはこんなとこ。
- 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); }
実行してみると…、ファイルは出来とる。
ファイルを開いてみたら、こんな感じ。
んまま、明日への自分へのメモってことで。