How to make a brush smooth without lines in the middle

enter image description here

Hi everyone, as you see in the previous brush, there are lines in the middle,
it is not so smooth how to make it smooth? (how to remove these lines) I create it with a mixture

<Grid x:Name="LayoutRoot"> <Grid.Background> <LinearGradientBrush EndPoint="0.452,1.962" StartPoint="1.164,-0.352"> <GradientStop Color="#FF202020" Offset="0"/> <GradientStop Color="#FF545454" Offset="1"/> </LinearGradientBrush> </Grid.Background> </Grid> 
+5
source share
3 answers

The strip is an artifact of the gradient algorithm. It should break the area in stripes, each of which is filled with a slightly different color. The edges are actually an optical illusion that makes them more visible than you think. To reduce this effect, you need to reduce the width of each strip.

Solutions:

  • Fill a smaller area - each strip is narrower.
  • Increase the number of ranges. Make the contrast between the two extremes bigger.
  • Increase the color resolution on the display. If you have more colors to choose from, then there will be a wider range of uses between the two colors of the end.

I understand that these decisions are either a) impossible or b) impractical. This is a problem that you will have to live with.

One practical solution would be to replace the brush with an image created in Photoshop or another image processing package. This may give you an image with a smaller range - but then you are limited by the size of the image - you cannot grow it without pixelation.

+9
source

Some time ago I wrote a smooth linear gradient for my WPF project. It removes the strip, but there are two caveats:

  • It cannot be used for anchored colors or {DynamicResource} .
  • It currently only supports vertical gradient, as that is all I need.

It is implemented as a dynamically created ImageBrush using Ordered Dithering . In addition, it is also MarkupExtension , since you cannot just inherit any Brush class (they are all sealed).

 /// <summary> /// Brush that lets you draw vertical linear gradient without banding. /// </summary> [MarkupExtensionReturnType(typeof(Brush))] public class SmoothLinearGradientBrush : MarkupExtension { private static PropertyInfo dpiX_; private static PropertyInfo dpiY_; private static byte[,] bayerMatrix_ = { { 1, 9, 3, 11 }, { 13, 5, 15, 7 }, { 1, 9, 3, 11 }, { 16, 8, 14, 6 } }; static SmoothLinearGradientBrush() { dpiX_ = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static); dpiY_ = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static); } /// <summary> /// Gradient color at the top /// </summary> public Color From { get; set; } /// <summary> /// Gradient color at the bottom /// </summary> public Color To { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { //If user changes dpi/virtual screen height during applicaiton lifetime, //wpf will scale the image up for us. int width = 20; int height = (int)SystemParameters.VirtualScreenHeight; int dpix = (int)dpiX_.GetValue(null); int dpiy = (int)dpiY_.GetValue(null); int stride = 4 * ((width * PixelFormats.Bgr24.BitsPerPixel + 31) / 32); //dithering parameters double bayerMatrixCoefficient = 1.0 / (bayerMatrix_.Length + 1); int bayerMatrixSize = bayerMatrix_.GetLength(0); //Create pixel data of image byte[] buffer = new byte[height * stride]; for (int line = 0; line < height; line++) { double scale = (double)line / height; for (int x = 0; x < width * 3; x += 3) { //scaling of color double blue = ((To.B * scale) + (From.B * (1.0 - scale))); double green = ((To.G * scale) + (From.G * (1.0 - scale))); double red = ((To.R * scale) + (From.R * (1.0 - scale))); //ordered dithering of color //source: http://en.wikipedia.org/wiki/Ordered_dithering buffer[x + line * stride] = (byte)(blue + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); buffer[x + line * stride + 1] = (byte)(green + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); buffer[x + line * stride + 2] = (byte)(red + bayerMatrixCoefficient * bayerMatrix_[x % bayerMatrixSize, line % bayerMatrixSize]); } } var image = BitmapSource.Create(width, height, dpix, dpiy, PixelFormats.Bgr24, null, buffer, stride); image.Freeze(); var brush = new ImageBrush(image); brush.Freeze(); return brush; } } 

Use of resources in the dictionary:

 <local:SmoothLinearGradientBrush x:Key="WindowBackgroundBrush" From="{StaticResource WindowBackgroundColorLight}" To="{StaticResource WindowBackgroundColorDark}" /> 

and then in management style:

 <Style ...> <Setter Property="Background" Value="{StaticResource WindowBackgroundBrush}" /> </Style> 
+8
source

Cheap and dirty option from my other answer:

Add a gradient to the container, give it a small negative margin so it spills a bit, add BlurEffect to the gradient, and then turn on ClipToBounds in the parent container. Thus, the gradient appears a little better due to performance.

Depending on your use case, this may be unsafe.

Example:

 <Grid Height="26" Margin="-5,0" ClipToBounds="True"> <Grid Margin="-5"> <Grid.Effect> <BlurEffect Radius="6" /> </Grid.Effect> <Grid.Background> <LinearGradientBrush> <GradientStop x:Name="GradientStop7" Color="Magenta" Offset="0.0" /> <GradientStop x:Name="GradientStop8" Color="DarkOrchid" Offset=".2" /> <GradientStop x:Name="GradientStop9" Color="Purple" Offset="1" /> </LinearGradientBrush> </Grid.Background> </Grid> </Grid> 

The negative gradient should be equal to the blur radius so that it does not become transparent at the edges.

0
source

All Articles