Алгоритм виньетирования изображения с помощью .NET - PullRequest
6 голосов
/ 14 января 2010

Мне бы хотелось узнать, как создать эффект виньетирования на изображении с использованием C # и .NET.

У кого-нибудь есть идеи, как это сделать? Или есть какие-нибудь ресурсы, для которых алгоритм уже будет сделан для меня?

Ответы [ 2 ]

10 голосов
/ 14 января 2010

Я верю, что это будет делать то, что вы хотите:

public void PaintVignette(Graphics g, Rectangle bounds)
{
    Rectangle ellipsebounds = bounds;
    ellipsebounds.Offset(-ellipsebounds.X, -ellipsebounds.Y);
    int x = ellipsebounds.Width - (int)Math.Round(.70712 * ellipsebounds.Width);
    int y = ellipsebounds.Height - (int)Math.Round(.70712 * ellipsebounds.Height);
    ellipsebounds.Inflate(x, y);

    using (GraphicsPath path = new GraphicsPath())
    {
        path.AddEllipse(ellipsebounds);
        using (PathGradientBrush brush = new PathGradientBrush(path))
        {
            brush.WrapMode = WrapMode.Tile;
            brush.CenterColor = Color.FromArgb(0, 0, 0, 0);
            brush.SurroundColors = new Color[] { Color.FromArgb(255, 0, 0, 0) };
            Blend blend = new Blend();
            blend.Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F };
            blend.Factors = new float[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f };
            brush.Blend = blend;
            Region oldClip = g.Clip;
            g.Clip = new Region(bounds);
            g.FillRectangle(brush, ellipsebounds);
            g.Clip = oldClip;
        }
    }
}

public Bitmap Vignette(Bitmap b)
{
    Bitmap final = new Bitmap(b);
    using (Graphics g = Graphics.FromImage(final)) {
        PaintVignette(g, new Rectangle(0, 0, final.Width, final.Height));
        return final;
    }
}

Что здесь происходит? Сначала я написал код, который бы залил прямоугольник кистью с эллиптическим градиентом от белого до черного. Затем я изменил код так, чтобы заполненная область также включала углы. Я сделал это, увеличив размер прямоугольника на разницу между размерами прямоугольника и sqrt (2) / 2 * размерами прямоугольника.

Почему sqrt (2) / 2? Поскольку точка (sqrt (2) / 2, sqrt (2) / 2) является точкой угла 45 градусов на единичной окружности. Масштабирование по ширине и высоте дает расстояние, необходимое для раздувания прямоугольника, чтобы убедиться, что он полностью покрыт.

Затем я отрегулировал наложение градиента, чтобы оно было намного более белым в центре.

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

Наконец, я написал служебный метод, который работает на растровом изображении (я не тестировал эту часть - я тестировал код на графике из Panel, но думаю, что он будет работать и здесь.

2 голосов
/ 14 января 2010

Если ваше изображение находится в файле, и если это достаточно быстро для ваших требований, вы можете использовать инструмент командной строки convert из ImageMagick , у него есть опция -vignette. Чтобы вызвать это из программы на C #, вы можете запустить ее через System.Diagnostics.Process.Start или использовать эту оболочку .NET для ImageMagick.

...