ビットマップの単純な拡大・縮小

単純なビットマップの拡大・縮小は、同じ画像処理アルゴリズムで実現できます。縮小とは「拡大率」が1未満の場合である、と考えれば良いからです。最も、拡大の場合は画質の劣化が避けられないので、それを何らかの形で補間する処理が必要になる場合もあるかもしれません。特に、整数分の位置の縮小や1.5倍の拡大、といった場合は以前作成した特別な場合の拡大・縮小処理の方が綺麗です。
 今回はとりあえず汎用性を重視し、ビットマップを任意の拡大率で単純に拡大・縮小してみましょう。

ビットマップの拡大・縮小

 ビットマップの拡大・縮小の画像処理は、ビットマップのピクセルを一定の割合で拾って新しいビットマップに描画して行く事で実現できます。縮小する時には、元のビットマップのピクセルを一定の率で「間引いて」描画して行く事になりますし、拡大するなら同じピクセルを何度か「重ねて」新しいビットマップに描画する事になるでしょう。この処理を縦横両方向に行えば、拡大・縮小を実現できます。

 例えば、1/2に縮小する(拡大率0.5)処理を考えてみましょう。この場合、元のビットマップを2ピクセル毎(1ピクセルおき)に「拾って」新しいビットマップに描画して行けば、元のビットマップを1/2に縮小して新しいビットマップに描画できます。また、2倍に拡大するなら元のビットマップのピクセル1つを2つ「重ねて」描画して行けば良いですね。
 この処理を一般化すれば、「元のビットマップのピクセルを1/拡大率ピクセル毎に新しいビットマップにコピーして行く」と言う事が出来ます。拡大率の逆数が1未満なら、元のビットマップの1ピクセルが1ピクセル以上の重みで描かれて「拡大」され、1より大きければ1ピクセルが1ピクセル未満の重みで描かれて(間引かれて)縮小されるわけです。

 ビットマップ(iWidth×iHeight)を、width×heightに拡大・縮小する関数は以下のようになります。ただし、この関数では元のビットマップに拡大・縮小の結果を上書きするので、拡大の場合はもとのビットマップからはみ出た部分が描画されません。また、拡大・縮小は原点(0,0)を合わせて行われます。

  void scale(int width,int height) { /* ビットマップの拡大・縮小処理 */

      int i,j,xx,yy;

      /* 作業用ビットマップをクリア */
      FillMemory(lpWork,iLength*iHeight,0xff);

      for (i=0;i<height;i++)  /* ビットマップを拡大・縮小 */
          for (j=0;j<width;j++) {

              /* 描画すべき元ビットマップのピクセルを計算 */
              xx=(int)(((double)iWidth/(double)width)*j);
              yy=(int)(((double)iHeight/(double)height)*i);

              /* 作業用ビットマップに元ビットマップのピクセルを描画 */
              if (j<iWidth && i<iHeight && xx<iWidth && yy<iHeight)
                  CopyMemory(lpWork+j*3+i*iLength,lpBMP+xx*3+yy*iLength,3);

          }

      /* 作業用ビットマップを表示用ビットマップにコピー */
      CopyMemory(lpBMP,lpWork,iLength*iHeight);

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

  }

プログラム

プログラムソース表示

 今回のプログラムは、フルカラービットマップを読みこんでそれを2/3、1.5倍に拡大・縮小します。まず、ドラッグ&ドロップするか読み込みボタンでビットマップを読みこんでから、「2/3」「1.5」ボタンで拡大・縮小してください。拡大・縮小を繰り返すと次第に画質が荒れてきますね。


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