Search code examples
c#uwpwin2d

Using Win2D, how to crop an image to a circle


It seems like this should be simple enough, but I'm really struggling with finding any documentation on how I can do this. I'm simply looking to crop an image to turn a square into a circle.

There is a lot of discussion about it, but I can't seem to find a good example of how to do this using UWP/Win2D.

Here is a bit of code to illustrate the issue I was trying to describe in my comments:

// draw a 10x10 grid of circles
var bitmap = await CanvasBitmap.LoadAsync(sender, "Assets/ice.png"); // hex-shaped image is 250x220 pixels 
var brush = new CanvasImageBrush(sender, bitmap);
for (var i = 0; i < 10; i++)
{
    for (var j = 0; j < 10; j++)
    {
        //_drawingSession.FillCircle(new Vector2(i * 50, j * 50), (float)(25), Colors.Blue);
        _drawingSession.FillCircle(new Vector2(i * 50, j * 50), (float)(25), brush);
    }
}

The image below shows how the brush is being cut from the same x/y coordinates based on the vector where the target circle is to be drawn.

Note: the same effect occurs with FillEllipse().

enter image description here


Solution

  • Okay, after chatting with one of the fellows on the GitHub Win2D project, I finally have a clear answer on how this works - and it works nothing like I would have expected it to work.

    First, the bitmap brush image is by default being positioned at 0,0 on the canvas.

    In my case, I wanted to cut a circle from the image and draw it someplace else on the canvas. This requires 2 separate bits of math.

    First, you need to position the bitmap's top-left-corner (TLC) to where you want the circle to be drawn. This is done by setting the brush's Transform property. In my example, I'm setting the image TLC to 300/300;

    // create the brush
    var brush = new CanvasImageBrush(sender, _tiles[1]);
    brush.Transform = Matrix3x2.CreateTranslation(300, 300);
    

    Now, to cut/draw the circle using the brush image, I have to describe where the center of the image is to be on the canvas. My image is 250x220.

    // 300+250/2, 300+220/2 = 425, 410
    _args.DrawingSession.FillCircle(new Vector2(425, 410), (float)(110), brush);
    

    This gives the effect of cutting a circle out of my original bitmap and drawing it on the canvas at the desired location.

    Hopefully this is clear enough. I know I certainly struggled to find the answer.