Title: Make a picture with a transparent hole in it in C#
The example Create oval images in C# shows how to make a transparent image with an oval-shaped picture in it. This example shows how to do the converse: it makes an image with a transparent hole in the middle of it.
There are several approaches that you might take. You might like to simply draw an ellipse filled with the color Color.Transparent on top of a picture. Unfortunately, when you use the color Color.Transparent, that tells the drawing system to not do anything. If you fill an ellipse with that color, then it simply isn't drawn.
A second approach would be to use the Bitmap class's MakeTransparent method to convert some other color into Color.Transparent. For example, you could fill an ellipse in the middle of the form with the color that has RGB components (0, 0, 1), which is practically black, and then use MakeTransparent to convert those pixels into Color.Transparent. Unfortunately, you would need to be sure that the image didn't already contain any pixels with the color (0, 0, 1). If it did, then those pixels would come out transparent, too. You can work around that problem by first examining the original image's pixels and converting any such pixels to black, which would be indistinguishable.
The approach that this post takes for making a transparent hole is to make a region representing all of the parts of the image except the hole. It then uses the region to fill a bitmap with the image, cropped to only act on the region.
The example Create oval images in C# explains the basic user interface: how the program handles mouse events and so forth. See that example for those details.
The big difference between that example and this one is the CutOutOval method that makes the image with the transparent hole. The following code shows that method.
private Bitmap CutOutOval(Point start_point, Point end_point)
{
// Make a region covering the whole picture.
Rectangle full_rect = new Rectangle(
0, 0, OriginalImage.Width, OriginalImage.Height);
Region region = new Region(full_rect);
// Remove the ellipse from the region.
Rectangle ellipse_rect =
SelectedRect(start_point, end_point);
GraphicsPath path = new GraphicsPath();
path.AddEllipse(ellipse_rect);
region.Exclude(path);
// Draw.
Bitmap bm = new Bitmap(OriginalImage);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.Clear(Color.Transparent);
// Fill the region.
gr.SetClip(region, CombineMode.Replace);
gr.SmoothingMode = SmoothingMode.AntiAlias;
using (TextureBrush brush =
new TextureBrush(OriginalImage, full_rect))
{
gr.FillRectangle(brush, full_rect);
}
}
return bm;
}
The code first makes a Rectangle that covers the image's entire area. It uses the Rectangle to make a new Region object.
Next, the code creates a second Rectangle to represent the area where the transparent hole should go. It creates a GraphicsPath object and adds the ellipse to it. The code then uses the Region object's Exclude method to exclude the ellipse from the Region.
At this point, the method starts drawing. It creates a new Bitmap that is a copy of the original image, and then makes an associated Graphics object. It clears the new Bitmap with the color Color.Transparent.
The code then calls the Graphics object's SetClip method to set its clipping rectangle to the region. After this point, the Graphics object will only modify pixels that lie within the region.
The rest is relatively straightforward. The program uses the original image to make a brush and then uses the brush to fill the entire Bitmap. The elliptical area that was excluded from the region is not drawn, resulting in a transparent hole.
After it creates the image, the program draws a checkerboard and draws the image on top of it to show the transparent hole.
Download the example to experiment with it and to see additional details.
|