Drawing image using Blur effects in UWP is not properly set size for the image

风格不统一 提交于 2021-01-29 08:20:51

问题


I want to blur the image using slider. For this, I have used Win2D Blur effects and draw the image in CanvasControl and added the canvas over the actual image.

Download sample here

Steps. 1. Added CanvasControl in button click. It will add a child to grid over the actual element 2. Change Slider to apply the blur 3. Issue: Image stretched and it's size too large and look like cropped. Not in the given size (500, 400)

[XAML]

<Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="7*"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
        <Grid x:Name="imageGrid">
            <Image x:Name="image" Source="Flower1.jpg" Width="500" Height="400"
                       HorizontalAlignment="Left" VerticalAlignment="Top"/>
        </Grid>
        <StackPanel Grid.Column="1" Orientation="Vertical">

            <Button Content="AddCanvas" Width="100" x:Name="addCanvas"
                        Click="AddCanvas_Click"/>

            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Blur" Width="100"/>
                <Slider x:Name="slider" Minimum="0" Maximum="5" Width="200"
                        ValueChanged="Slider_ValueChanged"/>
            </StackPanel>

        </StackPanel>
    </Grid>

[C#]

        bool isBlurred;
        GaussianBlurEffect blur = new GaussianBlurEffect();
        CanvasControl canv = new CanvasControl();
        CanvasBitmap cbi;

        public MainPage()
        {
            this.InitializeComponent();
        }
        private void AddCanvas_Click(object sender, RoutedEventArgs e)
        {
            canv.HorizontalAlignment = HorizontalAlignment.Left;
            canv.VerticalAlignment = VerticalAlignment.Top;
            canv.Draw += Canv_Draw;
            canv.CreateResources += Canv_CreateResources;
            canv.Height = 400;
            canv.Width = 500;

            imageGrid.Children.Add(canv);
        }

        private void Canv_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
        {
            args.DrawingSession.Units = CanvasUnits.Pixels;
            if (isBlurred)
            {
                args.DrawingSession.DrawImage(blur, new Rect(0, 0, 500, 400), new Rect(0, 0, 500, 400));
            }
        }

        private void Canv_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
        {
            args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());
        }
        async Task CreateResourcesAsync(CanvasControl sender)
        {
            cbi = await CanvasBitmap.LoadAsync(sender, "Flower1.jpg");
        }

        private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            isBlurred = true;
            blur.Source = cbi;
            blur.BlurAmount = (float)e.NewValue;
            canv.Invalidate();
        }

I would like to apply the Blur effects to the Image using slider dynamically. But i don't want to change the Actual image to Blur. So, I used Canvas over the Actual image and draw with Blur effect.

Regards,

Bharathi.


回答1:


Drawing image using Blur effects in UWP is not properly set size for the image

The problem is that the size of CanvasControl is not suit for image source (Image: 960*640 CanvasControl:500*400). If you want to make CanvasControl could display the full image, please set available dpi when call CanvasBitmap.LoadAsync method. For my testing 185 is suit for your scenario.

async Task CreateResourcesAsync(CanvasControl sender)
{
    cbi = await CanvasBitmap.LoadAsync(sender, "Flower1.jpg",185);

}

Update

//var dpi = DisplayInformation.GetForCurrentView().LogicalDpi;
var display = DisplayInformation.GetForCurrentView();
// calculate your monitor's dpi
var dpi = Math.Sqrt(Math.Pow(display.ScreenWidthInRawPixels, 2) + Math.Pow(display.ScreenHeightInRawPixels, 2)) / display.DiagonalSizeInInches;
// get the CanvasControl inch 
var inch = Math.Sqrt(Math.Pow(500, 2) + Math.Pow(400, 2)) / dpi;
// calculate last dpi with the image size
var lastdpi = Math.Sqrt(Math.Pow(960, 2) + Math.Pow(640, 2)) / inch;

Update 1

If could also set CanvasControl size with image size that could avoid to calculate Dpi.

Update 2

And you could also resize your image to suit for CanvasControl, Please refer the following code.

public async Task<IRandomAccessStream> ResizeImage(StorageFile file, int reqWidth, int reqHeight)
{
    var memStream = new MemoryStream();
    using (Stream stream = await file.OpenStreamForReadAsync())
    {
        stream.CopyTo(memStream);
    }
    IRandomAccessStream imageStream = memStream.AsRandomAccessStream();
    var decoder = await BitmapDecoder.CreateAsync(imageStream);
    if (decoder.PixelHeight > reqHeight || decoder.PixelWidth > reqWidth)
    {
        using (imageStream)
        {
            var resizedStream = new InMemoryRandomAccessStream();

            BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);
            double widthRatio = (double)reqWidth / decoder.PixelWidth;
            double heightRatio = (double)reqHeight / decoder.PixelHeight;

            double scaleRatio = Math.Min(widthRatio, heightRatio);

            if (reqWidth == 0)
                scaleRatio = heightRatio;

            if (reqHeight == 0)
                scaleRatio = widthRatio;

            uint aspectHeight = (uint)Math.Floor(decoder.PixelHeight * scaleRatio);
            uint aspectWidth = (uint)Math.Floor(decoder.PixelWidth * scaleRatio);

            encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear;

            encoder.BitmapTransform.ScaledHeight = aspectHeight;
            encoder.BitmapTransform.ScaledWidth = aspectWidth;

            await encoder.FlushAsync();

            return resizedStream;
        }
    }
    return imageStream;
}

Usage

async Task CreateResourcesAsync(CanvasControl sender)
{
    var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Flower1.jpg")); 
    cbi = await CanvasBitmap.LoadAsync(sender, await ResizeImage(file, 500, 400));    
}


来源:https://stackoverflow.com/questions/57572464/drawing-image-using-blur-effects-in-uwp-is-not-properly-set-size-for-the-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!