
BitmapをOpenGL向けの画像データに変換する
上の記事に System.Drawing.Image.Bitmap を使って画像ファイルをプログラム内に取り込む方法を書いた。
この記事では取り込んだ画像データを、OpenGL ライブラリを使って画面に表示するために、Bitmap の画像データを OpenGL 向けの画像データに変換するコードをメモしておく。
変換した画像データはテクスチャマッピングする。
Bitmapの画像データは、画像の左上隅のピクセルから順番に色データが並んでいる。色の並び順はB、G、R。
一方で OpenGL では、画像データは画像の左下隅のピクセルから順番に色データが並んでいると見なされる。Bitmapとは上下が逆で、左右は同じ。左から右、下から上に向かってデータが並ぶ。色の並び順はR、G、B。これも Bitmap とは逆。
これを踏まえ、Bitmap を OpenGL 向けの画像データに変換するプログラムは以下のようになる。
今回もコードは C++/CLI で書いている。
Bitmap を入力すると OpenGL 向けの画像データ配列 forGL を返す関数。
forGL は関数内で動的にアンマネージメモリ確保しているため、呼び出した側が使い終えたら delete[] する必要がある。
void BitmapToGL( Bitmap^ src, byte** forGL )
{
auto rect = System::Drawing::Rectangle( 0, 0, src->Width, src->Height );
Imaging::BitmapData^ bmpData = src->LockBits( rect,
Imaging:ImageLockMode::ReadOnly,
Imaging::PixelFormat::Format24bppRgb );
int w = bmpData->Width;
int h = bmpData->Height;
const byte* scan0 = (const byte*)bmpData->Scan0.ToPointer();
*forGL = new byte[3 * w * h]; // need to be delete[]
int iterator = 0;
for ( int j = 0 ; j < h ; ++j ) {
for ( int i = 0 ; i < w ; ++i ) {
int sIndex = i + w * j ;
int dIndex = i + w * ( h - j - 1 );
( *forGL )[3 * dIndex + 2] = scan0[iterator++]; // bmp B to OpenGL R
( *forGL )[3 * dIndex + 1] = scan0[iterator++]; // bmp G to OpenGL G
( *forGL )[3 * dIndex ] = scan0[iterator++]; // bmp R to OpenGL B
}
iterator = ( j + 1 ) * bmpData->Stride;
}
src->UnlockBits( bmpData );
}