大家好, 正如你在之前的画笔中看到的那样,中间有一些线条,它不是那么平滑 如何让它流畅? (如何删除那些行) 我用混合
创建它<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>
答案 0 :(得分:10)
条带是梯度算法的假象。它必须打破区域,每个区域都填充略有不同的颜色。边缘实际上是一种视错觉,其效果使它们比您想象的更加明显。要减少这种影响,您需要减小每个波段的宽度。
解决方案是:
我确实意识到这些解决方案要么a)不可能,要么b)不实用。这是你不得不忍受的问题。
一个实用的解决方案可能是用Photoshop或其他图像处理包中创建的图像替换画笔。这可能会给你一个带有较少条带的图像 - 但是你被限制在图像的大小 - 你不能在没有像素化的情况下成长它。
答案 1 :(得分:8)
前段时间我为WPF项目编写了平滑的线性渐变。它删除了条带,但有两个警告:
{DynamicResource}
。使用Ordered Dithering将其实施为动态创建的ImageBrush
。另外,它也是MarkupExtension
,因为我们不能简单地继承任何Brush
类(&#39;全部密封)。
/// <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;
}
}
资源字典中的用法:
<local:SmoothLinearGradientBrush x:Key="WindowBackgroundBrush"
From="{StaticResource WindowBackgroundColorLight}"
To="{StaticResource WindowBackgroundColorDark}" />
然后是控制风格:
<Style ...>
<Setter Property="Background" Value="{StaticResource WindowBackgroundBrush}" />
</Style>
答案 2 :(得分:0)
我的另一个答案是廉价而肮脏的选择:
将渐变添加到容器中,给它一个小的负边距,使其稍微溢出,向渐变添加BlurEffect,然后在父容器上启用ClipToBounds。这样,梯度就会以牺牲性能为代价而变得更好。
根据您的使用情况,这可能不太可行。
示例:
<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>
负梯度应该等于模糊半径,以便它不会在边缘变得透明。