IanG on Tap

Ian Griffiths in Weblog Form (RSS 2.0)

Blog Navigation

April (2018)

(1 item)

August (2014)

(1 item)

July (2014)

(5 items)

April (2014)

(1 item)

March (2014)

(1 item)

January (2014)

(2 items)

November (2013)

(2 items)

July (2013)

(4 items)

April (2013)

(1 item)

February (2013)

(6 items)

September (2011)

(2 items)

November (2010)

(4 items)

September (2010)

(1 item)

August (2010)

(4 items)

July (2010)

(2 items)

September (2009)

(1 item)

June (2009)

(1 item)

April (2009)

(1 item)

November (2008)

(1 item)

October (2008)

(1 item)

September (2008)

(1 item)

July (2008)

(1 item)

June (2008)

(1 item)

May (2008)

(2 items)

April (2008)

(2 items)

March (2008)

(5 items)

January (2008)

(3 items)

December (2007)

(1 item)

November (2007)

(1 item)

October (2007)

(1 item)

September (2007)

(3 items)

August (2007)

(1 item)

July (2007)

(1 item)

June (2007)

(2 items)

May (2007)

(8 items)

April (2007)

(2 items)

March (2007)

(7 items)

February (2007)

(2 items)

January (2007)

(2 items)

November (2006)

(1 item)

October (2006)

(2 items)

September (2006)

(1 item)

June (2006)

(2 items)

May (2006)

(4 items)

April (2006)

(1 item)

March (2006)

(5 items)

January (2006)

(1 item)

December (2005)

(3 items)

November (2005)

(2 items)

October (2005)

(2 items)

September (2005)

(8 items)

August (2005)

(7 items)

June (2005)

(3 items)

May (2005)

(7 items)

April (2005)

(6 items)

March (2005)

(1 item)

February (2005)

(2 items)

January (2005)

(5 items)

December (2004)

(5 items)

November (2004)

(7 items)

October (2004)

(3 items)

September (2004)

(7 items)

August (2004)

(16 items)

July (2004)

(10 items)

June (2004)

(27 items)

May (2004)

(15 items)

April (2004)

(15 items)

March (2004)

(13 items)

February (2004)

(16 items)

January (2004)

(15 items)

Blog Home

RSS 2.0

Writing

Programming C# 5.0

Programming WPF

Other Sites

Interact Software

How To Flood Fill in GDI+ (and Why You Don't Want To)

Sunday 29 August, 2004, 12:22 AM

From time to time, people ask what the GDI+ equivalent of certain GDI operations are. Sometimes there is no equivalent, and it's usually for a good reason. For example, I've already written about why XOR isn't supported. More recently, someone asked about how to do a flood fill in GDI+ on the DOTNET-WINFORMS mailing list.

He was hoping to be able to convert a GDI+ Brush object into a GDI32 HBRUSH. If such a thing were possible, that would have solved the problem, because GDI32 has the ExtFloodFill API. However, a GDI+ brush is a different kind of a thing from a GDI32 brush, so there's no way of converting between them.

Adrian Martin came up with a pragmatic solution to the problem. He suggested creating a bitmap containing the required fill pattern, and then using that bitmap to create a bitmap-based GDI32 HBRUSH. That's almost certainly the best solution, but I was curious to see if an alternative solution was possible.

So I've written a function that generates a Region object representing the region that would be filled if a flood fill were done. This means you can write this kind of code:

Region r = FloodFill.FloodFillUtils.GetRegionForFloodFill(originalImage, e.X, e.Y);
Bitmap bmp = new Bitmap(originalImage);
using (Graphics g = Graphics.FromImage(bmp))
{
    using (Brush b = new LinearGradientBrush(new Rectangle(new Point(), bmp.Size),
                Color.Red, Color.Magenta, LinearGradientMode.Vertical))
    {
        g.FillRegion(b, r);
    }
}

Since the Graphcs.FillRegion lets you use any GDI+ Brush, I think this solves the original problem - it lets you flood fill an area with any GDI+ Brush..

The following image illustrates why you probably don't want to do that in practice:

Example showing why flood fills don't work well in GDI+

This was generated using the snippet above. And as you can see it looks rather ropey - it appears not to have gone quite up to the edge of the interior of the circle. The reason for this is that the circle in question was drawn with anti-aliasing enabled. Flood fills are essentially fundamentally incompatible with antialiasing. This is because flood fills use pixel colours to determine boundaries, while anti-aliasing works by messing with pixel colours at the boundaries. And since antialiasing is essential for high quality imagery, this pretty much relegates the simple pixel-oriented single-colour-based flood fill to the history books - it is not a useful technique in the modern world.

That's not to say that the notion of filling a bounded area is useless. It's just that you need a vector-oriented equivalent instead, and the algorithms involved for that are rather different. (It would also be possible to implement a much more sophisticated pixel-based flood fill that knew all about anti-aliasing and took it into account I suppose.)

Despite its essential uselessness, the code required to achieve it illustrates some potentially interesting techniques for mixing and matching GDI+ and GDI32. And there will doubtless be situations in which some people will want a flood fill despite its intrinsic problems, so here's the code.

Copyright © 2002-2018, Interact Software Ltd. Content by Ian Griffiths. Please direct all Web site inquiries to webmaster@interact-sw.co.uk