Используя Win2D, как обрезать изображение до круга

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

Об этом много говорят, но я не могу найти хороший пример того, как это сделать с помощью UWP / Win2D.

Вот небольшой код, иллюстрирующий проблему, которую я пытался описать в своих комментариях:

// 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);
    }
}

На изображении ниже показано, как кисть обрезается с теми же координатами x / y на основе вектора, в котором должен быть нарисован целевой круг.

Примечание: тот же эффект происходит с FillEllipse ().

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


person Paul Mouchet    schedule 16.05.2018    source источник


Ответы (2)


Вы можете попробовать использовать CanvasImageBrush и Метод CanvasDrawingSession.FillEllipse.

private async void canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, 
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    using (CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(sender, "Assets/image.jpg"))
    {
        CanvasImageBrush canvasImageBrush = new CanvasImageBrush(sender, bitmap);
        args.DrawingSession.FillEllipse(new System.Numerics.Vector2(100f), 100, 100, canvasImageBrush);
    }
}

------------ Обновление -------------

Если вы хотите вырезать круг из источника изображения, вы можете настроить свойство CanvasImageBrush.Transform для масштабирования изображения, затем вырезать круг и отобразить его на холсте.

private async void canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, 
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    using (CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(sender, "Assets/image.jpg"))
    {
        CanvasImageBrush canvasImageBrush = new CanvasImageBrush(sender, bitmap);
        System.Numerics.Vector2 center = new System.Numerics.Vector2((float)(bitmap.Size.Width / 2),
            (float)(bitmap.Size.Height / 2));
        canvasImageBrush.Transform = System.Numerics.Matrix3x2.CreateScale(0.5F, center);
        args.DrawingSession.FillEllipse(center, 160, 160, canvasImageBrush);
    }
}

Вы должны изменить некоторые параметры в моем приведенном выше коде, чтобы удовлетворить ваши требования, например масштаб в методе Matrix3x2.CreateScale.

person Breeze Liu - MSFT    schedule 17.05.2018
comment
Кажется, что это работает, но похоже, что центральная точка (и, возможно, значения радиуса) используются как смещения в изображении, используемом для кисти. - person Paul Mouchet; 17.05.2018
comment
Когда я переключаю кисть на сплошной цвет, я успешно рисую сетку кругов. Однако при использовании кисти правильно нарисован только один из кругов. Остальные либо выглядят как мазки, либо изображение вообще не прорисовывается. - person Paul Mouchet; 17.05.2018
comment
После дальнейшего исследования мне кажется, что первый параметр в списке используется как целевые координаты того места, где рисуется эллипс, так и смещение от растрового изображения, используемого в качестве кисти. Похоже, поэтому все, что находится за пределами 220x250 (размер моего растрового изображения), отображается как размытые полосы. Я не уверен, является ли это ошибкой в ​​Win2D или это запланированная функция. - person Paul Mouchet; 17.05.2018
comment
Не могли бы вы предоставить больше кода, чтобы я увидел вашу проблему и желаемый эффект? - person Breeze Liu - MSFT; 18.05.2018
comment
Я обновил исходный пост, чтобы показать проблему, описанную выше. В моем случае я не собираюсь создавать сетку из кругов, но мне нужно использовать изображение в качестве источника, вырезать из него круг, а затем перерисовать этот круг на холсте. Сетка 10x10 показывает, что я не могу делать то, что хочу, используя FillCircle и растровую кисть. - person Paul Mouchet; 18.05.2018
comment
Похоже, я не первый, кто сообщает об этой проблеме. Однако я все еще застрял в том, как вырезать круг из исходного изображения и нарисовать круг на холсте. stackoverflow.com/ questions / 35730646 / - person Paul Mouchet; 18.05.2018
comment
Вы хотите вырезать изображение круга, которое является частью исходного изображения, а затем нарисовать изображение круга на холсте? Если это так, я думаю, вы можете изменить Vector2 (центр) и радиус, чтобы вырезать круг изображения на холсте. - person Breeze Liu - MSFT; 19.05.2018
comment
Я не понимаю, о чем вы говорите. У меня квадратное изображение. Я хочу вырезать круг из квадратного изображения, а затем нарисовать это изображение круга на холсте. Таким образом, я не могу использовать кисть холста, потому что, если я установлю целевые координаты на холсте в некоторую точку, которая больше изображения кисти, это не удастся. - person Paul Mouchet; 19.05.2018
comment
@PaulMouchet Я обновил свой ответ, вы можете проверить его и использовать преобразование, чтобы масштабировать изображение, чтобы вырезать его по своему усмотрению. - person Breeze Liu - MSFT; 21.05.2018
comment
Лю - предложение не улучшает ситуацию. Проблема с CanvasImageBrush заключается в том, что координаты, которые передаются в FillCircle / FillEllipse, используются как для смещения изображения кисти, так и холста. Это, безусловно, ошибка в том, как работают эти методы. Мое растровое изображение, которое я использую, имеет размер 250x220. Если я пытаюсь использовать растровую кисть при любых координатах холста, превышающих 250x220, операция не выполняется. Он не вылетает, но и не может нарисовать круг. Я попытался показать это в моем коде и на иллюстрации выше. Преобразование кисти не помогает. - person Paul Mouchet; 21.05.2018

Хорошо, после разговора с одним из участников проекта GitHub Win2D я наконец получил четкий ответ о том, как это работает - и он работает совсем не так, как я ожидал.

Во-первых, растровое изображение кисти по умолчанию располагается на холсте на 0,0.

В моем случае я хотел вырезать круг из изображения и нарисовать его в другом месте на холсте. Для этого требуются 2 отдельных математических элемента.

Во-первых, вам нужно расположить верхний левый угол (TLC) растрового изображения в том месте, где вы хотите нарисовать круг. Это делается путем установки свойства Transform кисти. В моем примере я устанавливаю TLC изображения на 300/300;

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

Теперь, чтобы вырезать / нарисовать круг с помощью изображения кисти, я должен описать, где должен быть центр изображения на холсте. Мое изображение 250x220.

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

Это дает эффект вырезания круга из моего исходного растрового изображения и рисования его на холсте в желаемом месте.

Надеюсь, это достаточно ясно. Я знаю, что я, конечно, изо всех сил пытался найти ответ.

person Paul Mouchet    schedule 23.05.2018