Region from Bitmap

A very common question is "I have a bitmap that I want to extract a shape from and then use that shape as the outline for a form. How can I get a region from a bitmap?"

This is accomplished using a simple raster scan analysis technique that scans an image line by line and pixel by pixel in much the same way as a television picture is built up on the screen. The interesting portions of the image are detected in some way and a description of the area is retained for later use.

In the case of a GDI+ Region object, the region of interest is described by an array of rectangles that tile to cover the area of the inside of the region. A simple program can be used to get a bunch of individual rectangles which are then combined with the original empty region object to create the mask for your image.

There are several techniques that can be used to extract this information including quite complex analysis of pixel colour or brightness but the simplest and most commonly used is to physically paint over the bits of the image that you don't want and allow the analysis program to give you rectangles that cover the rest.

In this example, I have taken an image, painted the bits I don’t need with some garish color not found in the original, in this case pure magenta, and then subjected the resulting image to analysis.

Figure 1 shows the original and treated image for comparison.

Figure 1: The original and treated images

When loaded into memory, the bitmap can be analysed with the simple routine shown in listing 1.

private Region GetRegion(Bitmap _img, Color color)

{

      Color _matchColor=Color.FromArgb(color.R,color.G,color.B);

      System.Drawing.Region rgn= new Region();

      rgn.MakeEmpty();

      Rectangle rc=new Rectangle(0,0,0,0);

      bool inimage=false;

      for(int y=0; y<_img.Height;y++)

      {

            for(int x=0;x<_img.Width;x++)

            {

                  if(!inimage)

                  {

                        if(_img.GetPixel(x,y)!=_matchColor)

                        {

                              inimage=true;

                              rc.X=x;

                              rc.Y=y;

                              rc.Height=1;

                        }

                  }

                  else

                  {

                        if(_img.GetPixel(x,y)==_matchColor)

                        {

                              inimage=false;

                              rc.Width=x-rc.X;

                              rgn.Union(rc);   

                        }

                  }

                                         

            }

            if(inimage)

            {

                  inimage=false;

                  rc.Width=_img.Width-rc.X;

                  rgn.Union(rc);   

            }

      }

      return rgn;

 }

 

The resulting region can be used to crop the original image, keeping only the bits not painted in by hand.

To accompany this article I have prepared a C# application that uses this technique to create a form the same shape as the bike in the picture. The outline of the region is also filled with color to illustrate its use as a graphics clipping region. Figure 2 shows this application in action. You can download this application from here.

Figure 2: A floating form shaped like a Triumph Bonneville and its outline used as a mask

 

 Return to the GDI+ FAQ

  Copyright Robert W. Powell 2003. All rights reserved