【C++/CLI】画像データの拡大縮小

画像表示の拡大縮小については画像の拡大縮小表示(高機能版)として紹介しましたが、今回は画像データのそのものを拡大縮小する方法を紹介します。

 

画像データを拡大縮小するにはSystem.Drawing.Bitmapクラスの以下のコンストラクタを用いる事で可能となります。

 

Bitmap (
    Image^ original,
    int width,
    int height
)

 

概要

指定したサイズを使用して、指定した既存のイメージで Bitmap クラスの新しいインスタンスを初期化します。

 

パラメータ

original 新しい Bitmap の作成元の Image
width 新しい Bitmap の幅 (ピクセル単位)
height 新しい Bitmap の高さ (ピクセル単位)

 

処理例

//元の画像
Bitmap^ src = gcnew Bitmap("test.bmp");
//縮小画像(1/2に縮小)
Bitmap^ dstSmall = gcnew Bitmap(src, src->Width / 2, src->Height / 2);
//画像の保存
dstSmall->Save("SmallImage.bmp", Imaging::ImageFormat::Bmp);
//拡大画像(2倍に拡大)
Bitmap^ dstBig = gcnew Bitmap(src, src->Width * 2, src->Height * 2);
//画像の保存
dstBig->Save("BigImage.bmp", Imaging::ImageFormat::Bmp);

 

処理結果

元の画像(test.bmp)

 

縮小画像(SmallImage.bmp)

 

拡大画像(BigImage.bmp)

 

補間モード(InterpolationMode)を指定して保存したい場合は、いったんGraphicsを通して画像を描画することで、補間モードを設定します。

 

//元の画像
Bitmap^ src = gcnew Bitmap("test.bmp");
//拡大画像データの確保
Bitmap^ dst = gcnew Bitmap(src->Width * 2, src->Height * 2);
//Graphicsオブジェクトの確保
Graphics^ g = Graphics::FromImage(dst);
//補間モードの設定
g->InterpolationMode = Drawing2D::InterpolationMode::HighQualityBicubic;
//拡大してGraphicsへ描画
g->DrawImage(src, 0, 0, src->Width * 2, src->Height * 2);
//画像の保存
dst->Save("BigImage.bmp", Imaging::ImageFormat::Bmp);

ただし、この方法では元の画像データ(src)がモノクロデータ(8Bit)の場合、上記のプログラムのままではR,G,Bの値が等しい24Bitのカラー画像として保存されてしまいます。
モノクロ画像データとして保存したい場合は、カラー画像からモノクロ画像に変換するしかなさそうです。

【C++/CLI】画像の拡大縮小表示(高機能版)

画像の拡大縮小表示(簡易版)のページでは、簡単に画像の拡大縮小表示する方法を紹介しましたが、画像サイズが大きいときなど、不都合な場合があるのですが、その時にはDrawImageメソッドを使って画像を拡大縮小表示します。

Win32APIのStretchDIBits関数に相当するのが、.NETではGraphicsクラスのDrawImageメソッドになります。
DrawImageメソッドには実に30個ものオーバーロードがあり、その分だけ高機能になっているのですが、詳細はMSDNに任せるとして、これまで慣れ親しんできたStretchDIBitsに近いメソッドを紹介します。

 

DrawImageの構文は以下の通り

void DrawImage (
	Image^ image,
	Rectangle destRect,
	Rectangle srcRect,
	GraphicsUnit srcUnit
)
image 描画するImageオブジェクト
通常はBitmapオブジェクトを渡す
destRect 描画先(ピクチャボックスなど)の描画領域
srcRect 描画するImageオブジェクトの領域
srcUnit srcRect パラメータで使用する単位を指定する GraphicsUnit 列挙体のメンバ
通常はGraphicsUnit::Pixelと指定すればOK

 

また、Win32APIのSetStretchBltModeのように伸縮モードを設定するには、.NETでは
GraphicsオブジェクトのInterpolationModeプロパティで設定します。

 

Default 規定の補間モード
High 高品質補間
Low 低品質補間
NearestNeighbor 最近傍補間
Bilinear 双一次補間
Bicubic 双三次補間
HighQualityBilinear 高品質双一次補間
HighQualityBicubic 高品質双三次補間

 

画像処理のプログラムでは画素の1つ1つが良くわかるNearestNeighborがオススメです。

 

ということで、画像を等倍で表示する場合は、srcRectとdestRectを同じサイズに指定します。

 

画像を n倍に拡大する場合は、srcRectをdestRectの1/n倍のサイズに指定します。

 

 

この処理のサンプルプログラムは以下に示しておきます。
ただし、エラー処理などはまるで無視しています。

 

 private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {

     //PictureBoxと同じ大きさのBitmapクラスを作成する。
     Bitmap^ bmpPicBox = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);
     //空のBitmapをPictureBoxのImageに指定する。
     pictureBox1->Image = bmpPicBox;
     //Graphicsクラスの作成(空のピクチャボックスからGraphicsを作成する)
     Graphics^g = Graphics::FromImage(pictureBox1->Image);

     //伸縮モードをNearestNeighborに設定
     g->InterpolationMode = Drawing2D::InterpolationMode::NearestNeighbor;

     //描画するビットマップ
     Bitmap^ bmp = gcnew Bitmap("c:\\test.bmp");
     //画像の描画
     int DrawScale = 5;
     g->DrawImage(bmp,
      System::Drawing::Rectangle(0, 0, pictureBox1->Width, pictureBox1->Height),
      System::Drawing::Rectangle(140, 100, pictureBox1->Width / DrawScale, pictureBox1->Height / DrawScale),
      GraphicsUnit::Pixel);
    }

 

実行画面