画像をタイル分割する

OpenGLで画像をテクスチャとして面に貼り付けるには、画像の縦横のサイズが2のべき乗数でなければならないという制約があります。
OpenGLの関数にそのように画像をリサンプルする関数(gluScaleImage())があるのですが、
大きな画像を分割したいときなんかはこの方法を使ったほうがいいでしょう。

以下の例は、画像を下図のように分割する例です。

/*
ビットマップをIMG_SIZE×IMG_SIZEのタイルに分割してそれぞれファイルに保存する
*/

void CreateTile
( BYTE *btImg, int iInX,
 int iInY, int *piOutX, int *piOutY, int iSamplePerPixel,
 int *piRowTileNum, int *piColTileNum, BYTE ***pOutImg )
{
    int            iTotalWidth, iTotalHeight;
    int            i, j, k, l, m, x = 0, y = 0, nPix, nRow;
    int            iCol, iRow;
    LPSTR        pInputBit, pImage, pImageBit;

    //全体の画像サイズ(IMG_SIZEの倍数)を求める
  iTotalWidth  = IMG_SIZE * (int)(ceil(iInX/IMG_SIZE));
  iTotalHeight = IMG_SIZE * (int)(ceil(iInY/IMG_SIZE));

  //縦横の分割数を計算する、上限はIMG_SIZE
  iColTileNum = (int)(iTotalWidth  / IMG_SIZE)+1;
  iRowTileNum = (int)(iTotalHeight / IMG_SIZE)+1;
  if ( !iRowTileNum ) iRowTileNum = 1;
  if ( !iColTileNum ) iColTileNum = 1;

  //分割画像の数分のポインタを取得する
  *OutImg = new BYTE*[iRowTileNum * iColTileNum];

  //ここで、2^nの領域を取得しておく
  for ( i = 0; i < iRowTileNum * iColTileNum; i++ )
  {
    (*pOutImg)[i] = new BYTE[IMG_SIZE*IMG_SIZE*iSamplePerPixel];
  }

  iCol = iColTileNum;
  iRow = iRowTileNum;
  //画像の縦横どちらかがIMG_SIZEを下回ったらファイル分割終了
  while ( (iTotalWidth / nSkip) >= IMG_SIZE || (iTotalHeight / nSkip) >= IMG_SIZE )
  {
    //左下の画像からコピー、
    for ( i = 0; i < iRow; i++ )
    {
      //最後のタイル行かどうかで半端かIMG_SIZEかが決まる
      i == iRow - 1 ? nRow = iInY % (IMG_SIZE*nSkip) : nRow = (IMG_SIZE*nSkip);
      for ( j = 0; j < iCol; j++ )
      {
        //出力用画像マトリックスの全ピクセルを0xFFにセット
        pImageBit = pImage;
        memset( pImage, 0xFF, IMG_SIZE*IMG_SIZE*iSamplePerPixel*sizeof(BYTE) );
        //現在のタイルの先頭にpBitをセット
        pInputBit = btImg;
        pInputBit += IMG_SIZE*(iInX*iSamplePerPixel)*i
				 + IMG_SIZE*nSkip*iSamplePerPixel*j;
        //最後のタイル列かどうかでコピーする幅を設定
        j == iCol-1 ? nPix = iInX % IMG_SIZE : nPix = IMG_SIZE;
        //1行ずつコピー
        for ( k = 0; k < nRow; k += nSkip )
        {
          //一列ずつコピー
          for ( l = 0; l < nPix; l += nSkip )
          {
            //ピクセルごとにコピー
            for ( m = 0; m < iSamplePerPixel; m++ )
            {
        (*pOutImg)[i*nCol+j][y*IMG_SIZE*iSamplePerPixel+x*iSamplePerPixel+m] =
                = pInputBit[l*iSamplePerPixel+m];
            }
            x++;
          }
          y++;
          x = 0;
          pInputBit += iInX*iSamplePerPixel;
        }
        y = 0;
      }
    }
  }

  *piOutX      =  iTotalWidth;
  *piOutY      =  iTotalHeight;
  *piRowTileNum  =  iRowTileNum;
  *piColTileNum  =  iColTileNum;
}
アーカイブ