在 UWP 中使用模糊效果绘制图像未正确设置图像大小
Posted
技术标签:
【中文标题】在 UWP 中使用模糊效果绘制图像未正确设置图像大小【英文标题】:Drawing image using Blur effects in UWP is not properly set size for the image 【发布时间】:2019-12-25 14:26:14 【问题描述】:我想使用滑块模糊图像。为此,我使用了 Win2D 模糊效果并在 CanvasControl 中绘制图像,并将画布添加到实际图像上。
下载示例here
步骤。 1. 按钮点击新增CanvasControl。它将在实际元素上添加一个子网格 2.更改滑块以应用模糊 3. 问题:图像被拉伸,尺寸太大,看起来像被裁剪了。不在给定的大小 (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();
我想动态地使用滑块将模糊效果应用于图像。但我不想将实际图像更改为模糊。因此,我在实际图像上使用了 Canvas 并使用模糊效果进行绘制。
问候,
婆罗提。
【问题讨论】:
Update2 工作吗? 【参考方案1】:在 UWP 中使用模糊效果绘制图像的图像大小未正确设置
问题是CanvasControl
的大小不适合图像源(图像:960*640 CanvasControl:500*400)。如果你想让 CanvasControl 可以显示完整的图像,请在调用 CanvasBitmap.LoadAsync
方法时设置可用的 dpi。对于我的测试,185 适合您的场景。
async Task CreateResourcesAsync(CanvasControl sender)
cbi = await CanvasBitmap.LoadAsync(sender, "Flower1.jpg",185);
更新
//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;
更新 1
如果还可以将CanvasControl
的大小设置为可以避免计算Dpi的图像大小。
更新 2
您还可以调整图像大小以适应 CanvasControl,请参考以下代码。
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;
用法
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));
【讨论】:
感谢提供解决方案。如果我设置 185,它工作正常。但是,我会上传不同大小的图像。所以,我无法确定图像的大小。请让我,如何一般地计算 dpi 值。我用下面的线。但它不工作。在我的系统中将 dpi 值返回为 13.99。请就此给我建议。 var dpi = DisplayInformation.GetForCurrentView().DiagonalSizeInInches; cbi = await CanvasBitmap.LoadAsync(sender, "Flower1.jpg", (float)dpi); 而且,这将在不同的系统中使用。所以我需要根据具体系统计算dpi值 @Bharathi,您还可以调整图像大小以适应 CanvasControl 我尝试了 dpi 和 lastdpi 值,但它在我的机器上不起作用。如果我使用 184.5,它在高度 (500,400) 上工作得很好。请让我知道我在这方面做错了什么。 cbi = await CanvasBitmap.LoadAsync(sender, "Flower1.jpg", (float)lastdpi); 现在,我从 Image SizeChanged 事件中删除了静态尺寸 (500, 400) 并设置了尺寸。这是实时场景。请从以下链接下载示例。 github.com/bharathirajauk/MySamples/blob/master/…以上是关于在 UWP 中使用模糊效果绘制图像未正确设置图像大小的主要内容,如果未能解决你的问题,请参考以下文章
ListView 未根据 sqlite 中的名称显示可绘制对象中的正确图像
使用 OpenGL-ES 绘制应用程序中的模糊效果(湿中湿效果)