Win2D: как нарисовать центральное изображение внутри круга масштабируемый

Я пытаюсь нарисовать масштабированное изображение внутри круга с помощью Win2D в С #, и мне это не удается.

Например, мои попытки:

    CanvasBitmap image;
    bool resourcesLoaded = false;
    public Other() {
        this.InitializeComponent();
    }
    void canvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args) {
        if( resourcesLoaded ) {
            var halfWidth = sender.ActualWidth / 2;
            var halfHeight = sender.ActualHeight / 2;

            double displayScaling = DisplayInformation.GetForCurrentView().LogicalDpi / 96.0;
            double pixelWidth = halfWidth * displayScaling;
            double pixelHeight = halfHeight * displayScaling;

            var scaleEffect = new ScaleEffect() {
                Source = image,
                Scale = new Vector2() {
                    X = ( float ) ( pixelHeight / image.Size.Height ),
                    Y = ( float ) ( pixelHeight / image.Size.Height ),
                }
            };
            var blurEffect = new GaussianBlurEffect() {
                Source = scaleEffect,
                BlurAmount = 5f
            };

            args.DrawingSession.FillCircle( new System.Numerics.Vector2() { X = ( float ) halfWidth, Y = (float) halfHeight },
              (float) halfHeight/2,
              new CanvasImageBrush( sender, blurEffect ) {
                  SourceRectangle = new Rect(0,0, scaleEffect.GetBounds(sender).Width, scaleEffect.GetBounds( sender ).Height)
              } );
        }
    }
    private void canvasControl_CreateResources(CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) {
        args.TrackAsyncAction( CreateResources( sender ).AsAsyncAction() );
    }
    private async Task CreateResources(CanvasControl sender) {
        image = await CanvasBitmap.LoadAsync( canvasControl, new Uri( "ms-appx:///Imgs/test.jpg" ) );
        resourcesLoaded = true;
        sender.Invalidate();
    }

И что происходит, так это то, что изображение кажется нарисованным в позиции X = 0 и Y = 0 окна (холст использует все окно), поэтому мой круг находится в середине окна, тогда только часть изображения нарисована и я хотел, чтобы мое изображение было помещено в центр круга.

Итак, вопросы: - Правильно ли поставлена ​​моя шкала? зачем делить на 96? я могу прочитать это из системы? - можно ли размыть только края изображения? - а как нарисовать свое изображение в центре круга?

Спасибо


person Nuno    schedule 27.02.2018    source источник


Ответы (1)


Думаю, мне удалось исправить свою проблему, сначала ответы на возможные вопросы:

  • правильно ли сделана моя шкала?

в следующем примере кода теперь они есть (масштаб должен использовать оба значения, с и высотой)

  • зачем делить на 96? я могу прочитать это из системы?

96 - это DPI, поэтому нам нужно получить текущий DPI, используемый вашей системой, мы можем вызвать CanvasControl.Dpi, чтобы узнать

  • и как я могу нарисовать свое изображение в центре круга?

ну, лучше показать код, чтобы ответить на этот вопрос, но в основном идея состоит в том, чтобы сделать все внутри CanvasCommandList, а затем нарисовать CanvasCommandList в любом месте окна:

    CanvasCommandList cl;
    CanvasBitmap image;
    bool resourcesLoaded = false;
    private void canvasControl_CreateResources(CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) {
        args.TrackAsyncAction( CreateResources( sender ).AsAsyncAction() );
    }
    private async Task CreateResources(CanvasControl sender) {
        image = await CanvasBitmap.LoadAsync( canvasControl, new Uri( "ms-appx:///Imgs/test.jpg" ) );
        int ratio = 6;
        var newImgWidth = image.Size.Width / ratio;
        var newImgHeight = image.Size.Height / ratio;

        double displayScaling = DisplayInformation.GetForCurrentView().LogicalDpi / sender.Dpi;
        double pixelWidth = newImgWidth * displayScaling;
        double pixelHeight = newImgHeight * displayScaling;

        cl = new CanvasCommandList( sender );
        using( CanvasDrawingSession clds = cl.CreateDrawingSession() ) {
            var scaleEffect = new ScaleEffect() {
                Source = image,
                Scale = new Vector2() {
                    X = ( float ) ( pixelWidth / image.Size.Width ),
                    Y = ( float ) ( pixelHeight / image.Size.Height ),
                }
            };
            var blurEffect = new GaussianBlurEffect() {
                Source = scaleEffect,
                BlurAmount = 5f
            };

            //don't now why but we need to do this in order to have the correct bounds size
            clds.DrawImage( blurEffect, 0, 0, new Rect( 0, 0, newImgWidth, newImgHeight ), 0.05f );
            //now draw the circle
            clds.FillCircle( ( float ) newImgWidth / 2, ( float ) newImgHeight / 2,
              ( float ) ( newImgWidth > newImgHeight ? newImgHeight : newImgWidth ) / 2,
              new CanvasImageBrush( sender, scaleEffect ) {
                  SourceRectangle = new Rect( 0, 0, newImgWidth, newImgHeight )
              } );
        }
        resourcesLoaded = true;
    }

    void canvasControl_Draw(CanvasControl sender, CanvasDrawEventArgs args) {
        if( resourcesLoaded ) {
            //cell (0,0)
            args.DrawingSession.DrawImage( cl,
                0,
                0 );
            args.DrawingSession.DrawRectangle( new Rect(
                0, 0,
                cl.GetBounds( sender ).Width, cl.GetBounds( sender ).Height ), Windows.UI.Colors.Red, 3 );
            //cell (0,1)
            args.DrawingSession.DrawImage( cl,
                ( float ) ( sender.ActualWidth - cl.GetBounds( sender ).Width ),
                ( float ) ( 0 ) );
            args.DrawingSession.DrawRectangle( new Rect(
                ( sender.ActualWidth - cl.GetBounds( sender ).Width ), 0,
                cl.GetBounds( sender ).Width, cl.GetBounds( sender ).Height ), Windows.UI.Colors.Green, 3 );
            //cell (1,0)
            args.DrawingSession.DrawImage( cl, ( float ) ( 0 ),
                ( float ) ( sender.ActualHeight - cl.GetBounds( sender ).Height ) );
            args.DrawingSession.DrawRectangle( new Rect(
                ( 0 ),
                ( sender.ActualHeight - cl.GetBounds( sender ).Height ),
                cl.GetBounds( sender ).Width, cl.GetBounds( sender ).Height ), Windows.UI.Colors.Yellow, 3 );
            //cell (1,1)
            args.DrawingSession.DrawImage( cl,
                ( float ) ( sender.ActualWidth - cl.GetBounds( sender ).Width ),
                ( float ) ( sender.ActualHeight - cl.GetBounds( sender ).Height ) );
            args.DrawingSession.DrawRectangle( new Rect(
                ( sender.ActualWidth - cl.GetBounds( sender ).Width ),
                ( sender.ActualHeight - cl.GetBounds( sender ).Height ),
                cl.GetBounds( sender ).Width, cl.GetBounds( sender ).Height ), Windows.UI.Colors.Orange, 3 );
        }
    }

Это правильно рисует 4 изображения круга в каждом углу окна, как ожидалось и желательно, единственная проблема, которая, я думаю, вероятно, является ошибкой, заключается в том, что если вы рисуете только круг в CanvasCommandList, границы этого составляют половину ожидаемого , для этого мне нужно нарисовать все изображение выцветшим, только чтобы убедиться, что границы соответствуют ожиданиям ... может быть, есть лучшее решение, но это лучшее, что я нашел.

person Nuno    schedule 03.03.2018