Question

The LinearGradientBrush in .net (or even in GDI+ as a whole?) seems to have a severe bug: Sometimes, it introduces artifacts. (See here or here - essentially, the first line of a linear gradient is drawn in the endcolor, i.e. a gradient from White to Black will start with a Black line and then with the proper White to Black gradient)

I wonder if anyone found a working workaround for this? This is a really annoying bug :-(

Here is a picture of the Artifacts, note that there are 2 LinearGradientBrushes:

alt text http://img142.imageshack.us/img142/7711/gradientartifactmm6.jpg

Was it helpful?

Solution

I have noticed this as well when using gradient brushes. The only effective workaround I have is to always create the gradient brush rectangle 1 pixel bigger on all edges than the area that is going to be painted with it. That protects you against the issue on all four edges. The downside is that the colors used at the edges are a fraction off those you specify, but this is better than the drawing artifact problem!

OTHER TIPS

You can use the nice Inflate(int i) method on a rectangle to get the bigger version.

I would finesse Phil's answer above (this is really a comment but I don't have that privilege). The behaviour I see is contrary to the documentation, which says:

The starting line is perpendicular to the orientation line and passes through one of the corners of the rectangle. All points on the starting line are the starting color. Then ending line is perpendicular to the orientation line and passes through one of the corners of the rectangle. All points on the ending line are the ending color.

Namely you get a single pixel wrap-around in some cases. As far as I can tell (by experimentation) I only get the problem when the width or height of the rectangle is odd. So to work around the bug I find it is adequate to increase the LinearGradientBrush rectangle by 1 pixel if and only if the dimension (before expansion) is an odd number. In other words, always round the brush rectangle up the the next even number of pixels in both width and height.

So to fill a rectangle r I use something like:

Rectangle gradientRect = r;
if (r.Width % 2 == 1)
{
    gradientRect.Width += 1;
}
if (r.Height % 2 == 1)
{
    gradientRect.Height += 1;
}
var lgb = new LinearGradientBrush(gradientRect, startCol, endCol, angle);
graphics.FillRectangle(lgb, r);

Insane but true.

At least with WPF you could try to use GradientStops to get 100% correct colors right at the edges, even when overpainting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top