как сделать кисть гладкой без линий посередине - PullRequest
6 голосов
/ 21 марта 2012

enter image description here

Привет всем, как вы видите в предыдущей кисти, есть линии в середине,это не так гладко, как сделать это гладко?(как убрать эти строки) я создаю его с помощью blend

<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>

Ответы [ 3 ]

10 голосов
/ 21 марта 2012

Полоска является артефактом градиентного алгоритма. Он должен разбить область на полосы, каждая из которых заполнена немного другим цветом. Края на самом деле представляют собой оптическую иллюзию, которая делает их более заметными, чем вы думаете. Чтобы уменьшить этот эффект, вам нужно уменьшить ширину каждой полосы.

Решения:

  1. Заполните меньшую область - каждая полоса уже.
  2. Увеличить количество полос. Увеличьте контраст между двумя крайностями.
  3. Увеличение цветового разрешения дисплея. Если у вас есть больше цветов для выбора, тогда будет больше полезного диапазона между двумя конечными цветами.

Я понимаю, что эти решения либо а) невозможны, либо б) не практичны. Это проблема, с которой вам придется жить.

Одним из практических решений может быть замена кисти изображением, созданным в Photoshop или другом пакете обработки изображений. Это может дать вам изображение с меньшим количеством полос - но тогда вы ограничены размером изображения - вы не сможете увеличить его без пикселизации.

8 голосов
/ 29 марта 2014

Некоторое время назад я написал плавный линейный градиент для своего проекта WPF.Он удаляет полосы, но есть две оговорки:

  • Он не может использоваться для цветов с привязкой к данным или {DynamicResource}.
  • В настоящее время он поддерживает только вертикальный градиент, поскольку это было всеНеобходимый

Он реализован в виде динамически созданного ImageBrush с использованием Ordered Dithering .Кроме того, это также MarkupExtension, поскольку нельзя просто наследовать любой класс Brush (все они запечатаны).

/// <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>
0 голосов
/ 21 апреля 2017

Дешевый и грязный вариант из другого моего ответа таков:

Добавьте градиент к контейнеру, установите для него небольшое отрицательное поле, чтобы он немного растекался, добавьте 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>

Отрицательный градиент должен быть равен радиусу размытия, чтобы он не стал прозрачным по краям.

...