Remove part of an image in C#


[Remove part of an image]

This example lets you remove part of an image. It lets you load an image file and then click and drag to select an area on the image. When you release the mouse, the program generates two new images: an image containing only the selected area and an image with the selected area removed. The other parts of both images are transparent. The program then displays the two new images drawn on top of a checkerboard pattern so you can see the transparent areas.

The following code shows the MakeImageWithArea method, which creates an image that contains only the selected area.

// Make an image that includes only the selected area.
private Bitmap MakeImageWithArea(Bitmap source_bm,
    List<Point> points)
{
    // Copy the image.
    Bitmap bm = new Bitmap(source_bm.Width, source_bm.Height);

    // Clear the selected area.
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.Transparent);

        // Make a brush that contains the original image.
        using (Brush brush = new TextureBrush(source_bm))
        {
            // Fill the selected area.
            gr.FillPolygon(brush, points.ToArray());
        }
    }
    return bm;
}

The method first creates a new bitmap that has the same dimensions as the source bitmap. It creates a Graphics object associated with the new bitmap and uses it to clear the bitmap, filling it with the Transparent color.

Next the code makes a TextureBrush. A TextureBrush fills objects with a repeating image. In this case, the program uses the source bitmap as the brush’s image. It then simply fills the selected area with the brush. The method then returns the new bitmap.

The code that creates an image with the selected area removed is a bit trickier. Ideally you would just start with a copy of the original bitmap and then fill the selected area with the Transparent color. Unfortunately when you draw, the program overlays the new color on top of the image’s existing colors. For example, if you draw with a 50% opaque color, the area drawn is only shaded by the partly opaque color. In this example, if you fill an area with a Transparent color, the background color shows through so the area is completely unaffected.

You could fill the area with some unusual color and then use the bitmap’s MakeTransparent method to make pixels with that color transparent. For example, you could use magenta or the color with RGB components 1, 1, 1, and hope the original image doesn’t contain any pixels with that color. However, there’s always a chance that the image does contain that color and then the program would make stray pixels transparent.

This example uses a different approach, which is shown in the following code.

// Make an image that includes only the selected area.
private Bitmap MakeImageWithoutArea(Bitmap source_bm,
    List<Point> points)
{
    // Copy the image.
    Bitmap bm = new Bitmap(source_bm);

    // Clear the selected area.
    using (Graphics gr = Graphics.FromImage(bm))
    {
        GraphicsPath path = new GraphicsPath();
        path.AddPolygon(points.ToArray());
        gr.SetClip(path);
        gr.Clear(Color.Transparent);
        gr.ResetClip();
    }
    return bm;
}

This code makes a copy of the original bitmap and creates a Graphics object associated with it. Next it creates a GraphicsPath object and adds the selected area’s points to it as a polygon. It calls the Graphics object’s SetClip method to restrict drawing operations to the GraphicsPath, and then uses the Graphics object’s Clear method to clear the bitmap with the Transparent color. Because SetClip restricts drawing to the selected area, this clears only the selected area.

After clearing the selected area, the code resets the bitmap’s clipping region and returns the bitmap.

The program has one more interesting piece of code. The MakeSampleImage method shown in the following code takes a bitmap as a parameter and draws it on top of a checkerboard pattern so you can see any transparent areas in the image.

// Make a sample showing transparent areas.
private Bitmap MakeSampleImage(Bitmap bitmap)
{
    const int box_wid = 20;
    const int box_hgt = 20;

    Bitmap bm = new Bitmap(bitmap.Width, bitmap.Height);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        // Start with a checkerboard pattern.
        gr.Clear(Color.White);
        int num_rows = bm.Height / box_hgt;
        int num_cols = bm.Width / box_wid;
        for (int row = 0; row < num_rows; row++)
        {
            int y = row * box_hgt;
            for (int col = 0; col < num_cols; col++)
            {
                int x = 2 * col * box_wid;
                if (row % 2 == 1) x += box_wid;
                gr.FillRectangle(Brushes.LightBlue,
                    x, y, box_wid, box_hgt);
            }
        }

        // Draw the image on top.
        gr.DrawImageUnscaled(bitmap, 0, 0);
    }
    return bm;
}

The method first creates a bitmap with the appropriate size and makes an associated Graphics object. It clears the bitmap with white and then uses nested for loops to draw a light blue checkerboard pattern.

The method then uses the Graphics object’s DrawImageUnscaled method to draw the original image on top and returns the result.

The rest of the program is reasonably straightforward. Download it to see how it works.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, geometry, graphics, mathematics and tagged , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *