2010.12. 7.
石立 喬

Visual C++ 2010 Expressを用いた易しい画像処理(1)

――原画像を読み込み、RGBとCMYの三色に分解する――

 技術者にとって、画像処理は自作プログラムを応用する主要な分野の一つである。画像処理のシリーズを始めるに当たり、最初に、画像処理の対象となる原画像を取り込み、RGBとCMYの三色に分解する方法を説明する。これにより、画像データの仕組みが理解できる。
 すでに公開されている「Visual C++ 2010 Expressの易しい使い方」シリーズに述べてあることは省略されていることが多いので、それらを十分参照してほしい。
 画像処理に使用する画像クラスの種類や違いについては、「画像処理に役立つ主なコードの使い方」を、画像の描画方法については、「画像処理結果をForm上に描画するためのGraphicsメソッドの使い方」を参照されたいが、一応、簡単に以下に述べる。

画像処理の対象として使用する原画像を準備する
 画像処理を行うには、元となる原画像が必要である。パソコン画面から考えると、画像処理の結果も合わせて表示しようとすると、原画像のサイズは、320×240程度が適当である。ファイル形式はBMP、JPEG、PNG、GIF、EXIF、TIFFのいずれでも良い。
 画像処理で頻繁に使用する、RGBへの分解やRGBからの合成など、ピクセル単位での操作には、Bitmapクラスが便利である。
 Bitmapクラスとして画像ファイルを読み込むには(下記の例は「マイピクチャ」に画像がある場合)、コンストラクタを用いて、
   Bitmap^ bmap=gcnew Bitmap("C:/Documens and Settings/Owner/My Documents/My Pictures/sample.jpg");
などを使用する。「/」(スラッシュ)の代わりに「\」も使用できるが、その場合は、「\\」のように必ずに二個使用すること。そうしないと、エスケープ記号と解釈される。
 「マイ ドキュメント/Visual Studio 2010/Projects/<プロジェクト名>/<プロジェクト名>」に原画像ファイルを置いておけば、パス指定の必要はなく、
   Bitmap^ bmap=gcnew Bitmap("sample.jpg");
で良い。
 原画像ファイルをImageクラスの画像にするには、
   Image^ img=Image::FromFile(”C:/Documens and Settings/Owner/My Documents/My Pictures/sample.jpg");
などを使用する。

Form上へ画像を表示する
 Imageクラスの画像に対しては、
   g->DrawImage(img,X0,Y0);
でForm上に簡単に描画することができる。
 Bitmapクラスの画像の場合も、
   g->DrawImage(bmap,X0,Y0);
で同様に描画できる。X0とY0は、画像の左上の座標である。

画像の各ピクセルを読み取り、それらをRGB三色に分解する
 上述の方法で取得したBitmapクラスの画像bmapをピクセル単位で読み取るには、ピクセル当りのColor構造体を下記のようにして取得し、
   Color color=bmap->GetPixel(i,j);
得られたcolorをRGBに分解するには、
   r=color.R;
   g=color.G;
   b=color.B;
を使用する。i、jは画像のX座標値、Y座標値である。

RGBからColor構造体を生成する
 r、g、bのデータからColor構造体のcolorを生成するには、
   Color color=Color::FromArgb(r,g,b);
を使用する。

画面上に点を打つ
 パソコン画面上に直接、点を打つには、
   g->FillRectangle(brush,x,y,1,1);
を使用する。
 しかし、直接描画するのではなく、
   Bitmap^ bmap=gcnew Bitmap(width,height);
で生成したbmapに対して、
   bmap->SetPixel(x,y,Color::Black);
でピクセル単位に描画したのち、
   g->DrawImage(bmap,X0,Y0;
で、bmapを一斉に画面に表示すれば、SetPixelが使える。ただし、この場合には、描画の過程を示すことができない。

RGBに分解するプログラム

 以下は、該当プロジェクトのフォルダにある原画像sample.PNGを読み込み、R、G、Bの各成分を表示するプログラムである。

private: System::Void Form1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) {

   int X0=10,Y0=10;
   int X1=340,Y1=10;
   int X2=10,Y2=260;
   int X3=340,Y3=260;   Graphics^ gr=e->Graphics;

   Color color_src,color_dest;
   Byte r,g,b;
   Brush^ brush1;

   //原画像のビットマップを生成する
   Bitmap^ bmap=gcnew Bitmap("sample.PNG");

   //原画像を左上に描画する
   gr->DrawImage(bmap,X0,Y0);

   //原画像をRGBに分解し、表示する
   for(int j=0;j<240;j++)
      for(int i=0;i<320;i++){
         color_src=bmap->GetPixel(i,j);
         r=color_src.R;
         g=color_src.G;
         b=color_src.B;

         //-------------- RGB分解 --------------------

        //R成分
         color_dest=Color::FromArgb(r,0,0);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X1+i,Y1+j,1,1);

         //G成分
         color_dest=Color::FromArgb(0,g,0);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X2+i,Y2+j,1,1);

         //B成分
         color_dest=Color::FromArgb(0,0,b);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X3+i,Y3+j,1,1);

         //-------------- RGB分解 --------------------

      }

}

CMYに分解するプログラム
 以下は、上記プログラムの一部を変更し、印刷で使われるCMY系への分解を行なうものである。変更部分のみを示す。

         //-------------- CMY分解 --------------------

         c=255-r;
         m=255-g;
         y=255-b;

         //C成分
         color_dest=Color::FromArgb(0,c,c);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X1+i,Y1+j,1,1);

         //M成分
         color_dest=Color::FromArgb(m,0,m);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X2+i,Y2+j,1,1);

         //Y成分
         color_dest=Color::FromArgb(y,y,0);
         brush1=gcnew SolidBrush(color_dest);
         gr->FillRectangle(brush1,X3+i,Y3+j,1,1);

         //-------------- CMY分解 --------------------


プログラムで得られた画面
 RGBへの分解は、真っ黒のディスプレイ上にそれらを加算して元に戻すので、白い部分は、R、G、Bともに最大の強さとなっている。すなわち、赤、緑、青が共に最も強い部分が白である。



 CMYへの分解は、真っ白の印刷用紙上にそれらを塗り重ねて元に戻すので、白い部分は、C、M、Yともにゼロ(真っ黒、すなわち塗らない)となっている。原画像で黒い部分ほど、CMYの色を濃く塗るので、ネガ状になる。



「Visual C++ の勉強部屋」(目次)へ