Enhancing JPEG, PNG, Text Using C# .NET Part 4 - Soft Edge Effect

Chelsea Devereaux - May 8 '23 - - Dev Community

The Soft Edges effect deflates non-transparent areas of the image by the specified amount, then applies the Gaussian blur effect to smooth the borders. The resulting image is used as a transparency mask for the original image. For example, you can see the result of applying the Soft Edges effect in MS Word:

JPEG/PNG/Text Soft Edge Effect C#

Let’s reproduce the same image in pure C# and save it as PNG.

The following code creates an image like this and saves it to image1.png:

JPEG/PNG/Text Soft Edge Effect C#

    using System.Drawing;
    using System.Numerics;
    using GrapeCity.Documents.Drawing;
    using GrapeCity.Documents.Imaging;

    using var bmp = new GcBitmap(600, 600, false);
    using (var g = bmp.CreateGraphics(Color.White))
    {
        g.Transform = Matrix3x2.CreateTranslation(100, 100);
        using var path = CreatePath(g, 400, 400);
        g.FillPath(path, Color.FromArgb(204, 51, 153));
        g.DrawPath(path, new Pen(Color.FromArgb(153, 153, 255), 28f));
    }
    bmp.SaveAsPng("image1.png");

    static IPath CreatePath(GcGraphics g, float w, float h)
    {
        float a = w * 0.5f;
        float b = h * 0.5f;
        var delta = Math.Min(w, h) * 0.1875f;
        float rx = a - delta;
        float ry = b - delta;
        rx *= rx;
        ry *= ry;
        float m = h / w;
        var ang = Math.Atan(m);
        float xb = a + (float)Math.Sin(ang) * delta * 0.5f;
        float yb = b - (float)Math.Cos(ang) * delta * 0.5f;
        float n = yb - m * xb;
        float c = n - b;
        float A = 1f / rx + m * m / ry;
        float B = (a / rx - m * c / ry) * 2;
        float C = a * a / rx + c * c / ry - 1;
        float D = (float)Math.Sqrt(B * B - A * C * 4);
        var x1 = (B + D) * 0.5f / A;
        var x2 = (B - D) * 0.5f / A;
        if (x2 < x1)
            (x2, x1) = (x1, x2);
        var y1 = m * x1 + n;
        var y2 = m * x2 + n;
        var x3 = w - x1;
        var x4 = w - x2;
        var y3 = h - y1;
        var y4 = h - y2;

        var path = g.CreatePath();
        path.AddEllipse(new RectangleF(0f, 0f, w, h), FigureEnd.Closed);
        path.SetFillMode(FillMode.Alternate);

        path.BeginFigure(new PointF(x1, y1));
        var aSeg = new ArcSegment()
        {
            Size = new SizeF(a - delta, b - delta),
            SweepDirection = SweepDirection.Clockwise,
            Point = new PointF(x2, y2)
        };
        path.AddArc(aSeg);
        path.EndFigure(FigureEnd.Closed);

        path.BeginFigure(new PointF(x3, y3));
        aSeg.Point = new PointF(x4, y4);
        path.AddArc(aSeg);
        path.EndFigure(FigureEnd.Closed);

        path.Close();
        return path;
    }
Enter fullscreen mode Exit fullscreen mode

As you can see, the inner and outer edges of the figure are sharp. Let’s make them smooth.

In the first stage, we draw the same figure on a transparent background:

    using var bmp = new GcBitmap(600, 600, false);
    using (var g = bmp.CreateGraphics(Color.Transparent))
    {
        g.Transform = Matrix3x2.CreateTranslation(100, 100);
        using var path = CreatePath(g, 400, 400);
        g.FillPath(path, Color.FromArgb(204, 51, 153));
        g.DrawPath(path, new Pen(Color.FromArgb(153, 153, 255), 28f));
    }
Enter fullscreen mode Exit fullscreen mode

The image in GcBitmap now looks like this:

JPEG/PNG/Text Soft Edge Effect C#

The next step is extracting the Alpha channel from the image to a separate GrayscaleBitmap:

    using var gs = bmp.ToGrayscaleBitmap(ColorChannel.Alpha);
Enter fullscreen mode Exit fullscreen mode

If we draw 0xFF values (opaque pixels) as white and 0x00 values (transparent pixels) as black, the GrayscaleBitmap (gs) looks like this:

JPEG/PNG/Text Soft Edge Effect C#

The magic occurs when we call the GrayscaleBitmap.ApplyGlow method passing a negative value in the first parameter (infRadius). The second parameter specifies the Gaussian blur radius in pixels:

    gs.ApplyGlow(-13, 16);
Enter fullscreen mode Exit fullscreen mode

It works the other way around compared to the Glow effect - all non-transparent areas are deflated instead of being inflated; as for the Glow effect:

JPEG/PNG/Text Soft Edge Effect C#

We can apply the resulting GrayscaleBitmap as a transparency mask to the source GcBitmap with transparent background:

    bmp.ApplyTransparencyMask(gs);
Enter fullscreen mode Exit fullscreen mode

Now the image in GcBitmap (bmp) looks like this:

Soft Edge Effect C#

The last step is converting the image background to opaque (the White color in this case). Also, we can save the resulting image to a file:

    bmp.ConvertToOpaque(Color.White);
    bmp.SaveAsPng("image2.png");
Enter fullscreen mode Exit fullscreen mode

The image2.png file contains the expected result of our manipulations:

Soft Edge Effect C#

Applying Soft Edges can be slow if the deflation radius is large.

GrapeCity’s .NET Imaging API Library

This article only scratches the surface of the full capabilities of the GrapeCity Documents for Imaging (GcImaging). Review our documentation to see the many available features, and our demos to see the features in action with downloadable sample projects.

Integrating this .NET imaging server-side API into a desktop or web-based application allows developers to programmatically create and manipulate images at scale and load, process, and save images across many different formats.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .