ビットマップの拡大縮小処理

ビットマップの拡大・縮小処理を関数にまとめてみます。関数の形としては、ビットマップの大きさとビットマップのポインタを渡すとビットマップを指定した大きさに拡大/縮小するようにしました。

ビットマップの形式と関数

まず、今回扱うビットマップ画像はフルカラー24ビットで、BITMAPINFOの後にビットマップバッファが続く形式とします。関数の形は、

void resizeBMP(DWORD,DWORD,DWORD,DWORD,LPVOID*);

という形式で、引数はビットマップの現在の大きさ、拡大/縮小処理後の大きさ、ビットマップのアドレスを格納したポインタへのポインタ、となっています。この関数を呼び出すと、引数で渡したポインタに拡大・縮小後のビットマップ画像データが入っているわけです。

拡大縮小処理では、まずビットマップの元の大きさと変更後の大きさを保存・計算します。大きさが決まれば、後は以前と同様の処理を行うだけですね。汎用性を持たせるために、ビットマップの処理に使うバッファも関数内で確保・解放し、「外部」とのやりとりは引数のみとしました。この関数は、引数以外のグローバル変数などには依存しないので、他プログラムに直接組み込む事が出来ます。

  /* ビットマップの拡大・縮小処理 */
  void resizeBMP(DWORD sw,DWORD sh,DWORD width,DWORD height,LPVOID *lpSRC) { 

      LPBITMAPINFO lpInfo;
      LPVOID lpWork;
      LPBYTE lpPixel,lpSPixel;
      DWORD i,j,x,y,dwSLength,dwWidth,dwHeight,dwLength;

      if ((sw*3) % 4==0) /* 元画像の1ラインの長さを計算 */
          dwSLength=sw*3;
      else
          dwSLength=sw*3+(4-(sw*3) % 4);

      if ((width*3) % 4==0) /* ビットマップの1ラインの長さを計算 */
          dwLength=width*3;
      else
          dwLength=width*3+(4-(width*3) % 4);

      /* 作業用バッファを確保し元画像をコピー */
      lpWork=GlobalAlloc(GPTR,GlobalSize(*lpSRC));
      CopyMemory(lpWork,*lpSRC,GlobalSize(*lpSRC));

      dwWidth=width;
      dwHeight=height;

      /* ビットマップのメモリ再確保 */
      GlobalFree(*lpSRC);
      *lpSRC=GlobalAlloc(GPTR,sizeof(BITMAPINFO)+dwLength*dwHeight);

      /* ビットマップのBITMAPINFO構造体をコピー */
      CopyMemory(*lpSRC,lpWork,sizeof(BITMAPINFO));

      /* ビットマップの大きさ設定 */
      lpInfo=*lpSRC;
      lpInfo->bmiHeader.biWidth=dwWidth;
      lpInfo->bmiHeader.biHeight=dwHeight;

      /* ビットマップと元画像のビットマップバッファ取得 */
      lpPixel=(LPBYTE)((LPBYTE)*lpSRC+sizeof(BITMAPINFO));
      lpSPixel=(LPBYTE)((LPBYTE)lpWork+sizeof(BITMAPINFO));

      for (i=0;i<dwHeight;i++) /* 拡大・縮小コピー */
          for (j=0;j<dwWidth;j++) {

              /* 元画像の対応ピクセルを計算 */
              x=(int)(((double)sw/(double)dwWidth)*j);
              y=(int)(((double)sh/(double)dwHeight)*i);

              /* 対応ピクセルをビットマップにコピー */
              CopyMemory(lpPixel+j*3+i*dwLength,lpSPixel+x*3+y*dwSLength,3);

          }

      GlobalFree(lpWork);

  }

プログラム

 今回のプログラムでは、ビットマップの大きさを設定・表示するエディトボックスを入れてみました。ビットマップを読み込むとここにビットマップの大きさが表示され、ここに大きさを入れて「サイズ変更」ボタンをクリックするとビットマップの大きさが変更されます。

  case 0: /* サイズ変更ボタン */

      /* エディトボックスから大きさ取得 */
      if (GetWindowText(hwWidth,lpszStr,16)>0) {

          w=atoi(lpszStr); /* 文字列を数値化 */

          if (w<1)
              w=dwWidth;

          } else
              w=dwWidth;

          if (GetWindowText(hwHeight,lpszStr,16)>0) {

              h=atoi(lpszStr);

              if (h<1)
                  h=dwHeight;

          } else
              h=dwHeight;

          resizeBMP(dwWidth,dwHeight,w,h,&lpBMP); /* 拡大・縮小 */

          dwWidth=w; /* ビットマップの大きさ再設定 */
          dwHeight=h;
          if ((dwWidth*3) % 4==0)
              dwLength=dwWidth*3;
          else
              dwLength=dwWidth*3+(4-(dwWidth*3) % 4);

          /* エディトボックスにビットマップの大きさ表示 */
          wsprintf(lpszStr,"%d",dwWidth);
          SetWindowText(hwWidth,lpszStr);
          wsprintf(lpszStr,"%d",dwHeight);
          SetWindowText(hwHeight,lpszStr);

          InvalidateRgn(hwnd,NULL,FALSE);
          UpdateWindow (hwnd);             /* 再描画 */

          break;

プログラムソース表示

 プログラムを起動したら、適当なビットマップファイルをドラッグ&ドロップして読み込んでください。後は、大きさを指定して「サイズ変更」ボタンをクリックすると拡大・縮小処理が行われます。


プログラミング資料庫 > DIB/Waveによる音声画像処理実験室