3

I'm working with ImageSharp to do some basic image editing in my UWP app, and one of the things I need to do is to crop the image to a circle (you can assume the image is already a square).

I couldn't find a Clip API that worked with anything else that rectangles, so I came up with the following snippet:

// Image is an Image<Argb32> instance
image.Mutate(context =>
{
    context.Apply(target =>
    {
        double half = target.Height / 2.0;
        unsafe
        {
            fixed (Argb32* p = target.GetPixelSpan())
                for (int i = 0; i < target.Height; i++)
                    for (int j = 0; j < target.Width; j++)
                        if (Math.Sqrt((half - i).Square() + (half - j).Square()) > half)
                            p[i * target.Width + j] = default;
        }
    });
});

NOTE: that Square method is just an extension that takes a double and returns its squared value.

Now, this works fine, and it's reasonably fast as I'm working with small enough images (say, <= 250 pixels for each axis). This snippet simply sets each pixel that falls outside of the circle with radius height / 2, centered at the center of the image, to a transparent pixel.

I wonder though if there wasn't another more intuitive method to do the same thing, that I just missed.

Thank you for your help!

Sergio0694
  • 4,447
  • 3
  • 31
  • 58
  • I'm voting to close this question as off-topic because the OP has a working solution but is asking for a better way. This belongs on [codereview.se] – Daniel A. White Jan 30 '19 at 14:37
  • 1
    @DanielA.White this is not really a code review question though: I'm not asking users to review and possibly improve my code, I'm asking the library authors or users more familiar with it if there's some built-in method to achieve the same thing that I missed. – Sergio0694 Jan 30 '19 at 14:41
  • Doesn't SKCanvas.DrawRoundRect with the radius half to the length of the square image do the magic ? https://learn.microsoft.com/en-us/dotnet/api/skiasharp.skcanvas.drawroundrect?view=skiasharp-1.68.0 – mesimplybj Jan 30 '19 at 14:55
  • 1
    @mesimplybj Could be, but I've specifically asked for a solution using ImageSharp (even tagged the question), as I'm also using it to do other image modifications in my app. Suggesting to switch to an entirely different library isn't really what I was looking for, sorry. – Sergio0694 Jan 30 '19 at 15:00
  • 2
    Check out https://github.com/SixLabors/Samples/blob/master/ImageSharp/AvatarWithRoundedCorner/Program.cs this demoes how to use paths to fill the corners of the image with transparency. Should be much faster. – James South Feb 07 '19 at 01:46
  • Hey @JamesSouth - thank you for your answer. I tried the snippet you posted, both with all the available `PixelColorBlendingMode` options (the one in the snippet is no longer available) and with various values for the circle radius, but I had no luck. The resulting image is always identical to the initial image. I'm not sure what I'm doing wrong, as I've just copy-pasted the snippet above – Sergio0694 Feb 20 '19 at 11:11
  • @Sergio0694 The sample has now been updated to beta6 – James South Feb 20 '19 at 23:31
  • Hey @JamesSouth - thank you for the update. I've tested the new code, and while it's ~18x slower than my implementation, the final result is of course much smoother, so I'll gladly use this version over my own (as it's still pretty fast when working with small images anyway). Thank you for your help, you can post that as an answer so I can mark it as valid! – Sergio0694 Feb 21 '19 at 00:02

0 Answers0