Как сделать плавный градиент? C#

Уже день не могу найти решения проблемы с градиентом. Когда создаю градиент тёмных оттенков появляются ступеньки - переходы цветов, а это выглядит безобразно. Мой код:

<Grid.Background>
   <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
     <GradientStop Color="#FF1C1C1C" Offset="0"/>
     <GradientStop Color="Black" Offset="1"/>
   </LinearGradientBrush>
</Grid.Background>

Проблема на картинке

Размер окна 960 на 640.

Как должно быть - Фигма


Ответы (1 шт):

Автор решения: aepot

Как я и думал, фигма использует наложение шума (dithering) при отрисовке градиента. Такой встроенной штуки в WPF нет. Один из простых вариантов, это отрендерить картинку размером с окно сразу с градиентом и положить ее на фон. Если постараться, можно сделать это не медленнее, чем WPF отрисовывает сам градиент (5-10 мс). Само собой при изменении размера окна придется перерендеривать картинку заново.

Оставить лесенку нельзя, так как в моих планах это убрать.

Пример, как отрендерить фоновую картинку самому.

using System.Drawing;
using System.Drawing.Imaging;
static unsafe void Main(string[] args)
{
    using Bitmap bmp = new(960, 640, PixelFormat.Format8bppIndexed);
    const double gray = 28;
    BitmapData bmpData = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size), ImageLockMode.WriteOnly, bmp.PixelFormat);
    int p = bmp.Width + bmp.Height;
    Random rnd = Random.Shared;
    byte* ptr = (byte*)bmpData.Scan0;
    for (int row = 0; row < bmp.Height; row++)
    {
        byte* offset = ptr + row * bmpData.Stride;
        for (int col = 0; col < bmp.Width; col++)
        {
            *(offset + col) = (byte)Math.Clamp((int)(gray - gray * (col + row) / p + rnd.NextDouble() - 0.5), 0, 255);
        }
    }
    bmp.UnlockBits(bmpData);

    ColorPalette pal = bmp.Palette;
    for (int c = 0; c < 256; c++)
        pal.Entries[c] = Color.FromArgb(c, c, c);
    bmp.Palette = pal;

    bmp.Save("image.png", ImageFormat.Png);
}

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

введите сюда описание изображения

Дальше остается просто положить на фон и готово. Сохранять на диск при этом конечно же не следует.

→ Ссылка