OpenGLでの描画内容の画像化と保存

OpenGLで描画した情報をピクセル単位で取得し、画像化および保存したかったので、調べてみました。

OpenGLのglReadBufferとglReadPixels関数を使うようです。
一つのまとまった小さなプログラムコードは、探した限りでは無かったので書いてみました。
OpenCVを画像の保存に使っていますが、取得したピクセル情報は変数dataBufferに入っているので、
あとは自分の好きなように格納できると思います。

void saveImage( const unsigned int imageWidth, const unsigned int imageHeight )
{
  const unsigned int channnelNum = 3; // RGBなら3, RGBAなら4
  void* dataBuffer = NULL;
  dataBuffer = ( GLubyte* )malloc( imageWidth * imageheight * channelNum );

  // 読み取るOpneGLのバッファを指定 GL_FRONT:フロントバッファ GL_BACK:バックバッファ
  glReadBuffer( GL_BACK );

  // OpenGLで画面に描画されている内容をバッファに格納
  glReadPixels(
	0,                 //読み取る領域の左下隅のx座標
	0,                 //読み取る領域の左下隅のy座標 //0 or getCurrentWidth() - 1
	imageWidth,             //読み取る領域の幅
	imageHeight,            //読み取る領域の高さ
	GL_BGR, //it means GL_BGR,           //取得したい色情報の形式
	GL_UNSIGNED_BYTE,  //読み取ったデータを保存する配列の型
	dataBuffer      //ビットマップのピクセルデータ(実際にはバイト配列)へのポインタ
	);

  GLubyte* p = static_cast<GLubyte*>( dataBuffer );
  std::string fname = "outputImage.jpg";
  IplImage* outImage = cvCreateImage( cvSize( imageWidth, imageHeight ), IPL_DEPTH_8U, 3 );

  for ( unsigned int j = 0; j < imageHeight; ++ j )
  {
    for ( unsigned int i = 0; i < imageWidth; ++i )
    {
      outImage->imageData[ ( imageHeight - j - 1 ) * outImage->widthStep + i * 3 + 0 ] = *p;
      outImage->imageData[ ( imageHeight - j - 1 ) * outImage->widthStep + i * 3 + 1 ] = *( p + 1 );
      outImage->imageData[ ( imageHeight - j - 1 ) * outImage->widthStep + i * 3 + 2 ] = *( p + 2 );
      p += 3;
    }
  }

  cvSaveImage( fname.c_str(), outImage );
}

廣瀬