直接应用于文件和 UIElement 时,Win 2D 会产生不同的效果级别
Win 2D producing different effect level when applied directly on a file and UIElement
我在图像文件(存储文件)上应用 Win2D 高斯模糊,并直接在 UIElement - 图像(这是 XAML 图像)上应用,我看到 BlurAmount 的值相同为存储文件输出和 XAML 图像获取不同的输出..
原图
100% 模糊应用于 XAML 图像(或任何 UIElement)时的输出
100% 模糊应用于存储文件时的输出
相关代码:
对于图像文件:
using (var stream = await originalFile.OpenAsync(FileAccessMode.Read))
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device, bitmap.SizeInPixels.Width, bitmap.SizeInPixels.Height, bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = eo.effectAmount1;
blur.BorderMode = EffectBorderMode.Hard;
blur.Source = bitmap;
ds.DrawImage(blur);
}
var saveFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("ImageName.jpg", CreationCollisionOption.GenerateUniqueName);
using (var outStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
await renderer.SaveAsync(outStream, CanvasBitmapFileFormat.Png,1.0f);
}
}
对于 UIElement(XAML 图片) :
using (var stream = await sourceElement.RenderToRandomAccessStream())
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device,bitmap.SizeInPixels.Width,
bitmap.SizeInPixels.Height,
bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = blurAmount;
blur.Source = bitmap;
blur.BorderMode = EffectBorderMode.Hard;
ds.DrawImage(blur);
}
stream.Seek(0);
await renderer.SaveAsync(stream, CanvasBitmapFileFormat.Png);
}
问题:这是预期的行为吗?如果是,我怎样才能使两种情况具有相同的输出?如果不是,我做错了什么?
你能试试用 bitmap.Size
代替 bitmap.SizeInPixels
吗?
var renderer = new CanvasRenderTarget(bitmap, bitmap.Size);
我猜您正在经历模糊效果和像素化。
编辑 1
如果这不起作用,请在创建渲染器后放置此断言。 SizeInPixels 需要匹配:
Debug.Assert(
bitmap.SizeInPixels.Width == renderer.SizeInPixels.Width
&& bitmap.SizeInPixels.Height == renderer.SizeInPixels.Height
);
编辑 2
如果像素没问题,请尝试将图像元素上的 StretchMode
设置为 None
。
<Image Stretch="None" />
我只是怀疑视觉树中某处的像素化。
说明
您需要适应 DPI 比例。您的屏幕可能设置为 200%。因此,如果您有一个尺寸为 100x100 的 Image
控件,您实际上需要 200x200 像素的图像来填充它。如果你给它一个 100x100 的位图源,那么它会拉伸它以适应。这就是你得到像素化的原因。
因此,要解决您的问题,要么禁用图像上的任何拉伸,要么根据 DPI 比例缩小的源大小调整图像大小。也就是说,对于 200% DPI 比例的 100x100 像素图像,将图像宽度和高度设置为 50x50。
DPI 比例可以在 UI 线程上使用:
var dpiScale = DisplayInformation.GetForCurrentView().LogicalDpi / 96f;
我在图像文件(存储文件)上应用 Win2D 高斯模糊,并直接在 UIElement - 图像(这是 XAML 图像)上应用,我看到 BlurAmount 的值相同为存储文件输出和 XAML 图像获取不同的输出..
原图
100% 模糊应用于 XAML 图像(或任何 UIElement)时的输出
100% 模糊应用于存储文件时的输出
相关代码:
对于图像文件:
using (var stream = await originalFile.OpenAsync(FileAccessMode.Read))
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device, bitmap.SizeInPixels.Width, bitmap.SizeInPixels.Height, bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = eo.effectAmount1;
blur.BorderMode = EffectBorderMode.Hard;
blur.Source = bitmap;
ds.DrawImage(blur);
}
var saveFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("ImageName.jpg", CreationCollisionOption.GenerateUniqueName);
using (var outStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
await renderer.SaveAsync(outStream, CanvasBitmapFileFormat.Png,1.0f);
}
}
对于 UIElement(XAML 图片) :
using (var stream = await sourceElement.RenderToRandomAccessStream())
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device,bitmap.SizeInPixels.Width,
bitmap.SizeInPixels.Height,
bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = blurAmount;
blur.Source = bitmap;
blur.BorderMode = EffectBorderMode.Hard;
ds.DrawImage(blur);
}
stream.Seek(0);
await renderer.SaveAsync(stream, CanvasBitmapFileFormat.Png);
}
问题:这是预期的行为吗?如果是,我怎样才能使两种情况具有相同的输出?如果不是,我做错了什么?
你能试试用 bitmap.Size
代替 bitmap.SizeInPixels
吗?
var renderer = new CanvasRenderTarget(bitmap, bitmap.Size);
我猜您正在经历模糊效果和像素化。
编辑 1
如果这不起作用,请在创建渲染器后放置此断言。 SizeInPixels 需要匹配:
Debug.Assert(
bitmap.SizeInPixels.Width == renderer.SizeInPixels.Width
&& bitmap.SizeInPixels.Height == renderer.SizeInPixels.Height
);
编辑 2
如果像素没问题,请尝试将图像元素上的 StretchMode
设置为 None
。
<Image Stretch="None" />
我只是怀疑视觉树中某处的像素化。
说明
您需要适应 DPI 比例。您的屏幕可能设置为 200%。因此,如果您有一个尺寸为 100x100 的 Image
控件,您实际上需要 200x200 像素的图像来填充它。如果你给它一个 100x100 的位图源,那么它会拉伸它以适应。这就是你得到像素化的原因。
因此,要解决您的问题,要么禁用图像上的任何拉伸,要么根据 DPI 比例缩小的源大小调整图像大小。也就是说,对于 200% DPI 比例的 100x100 像素图像,将图像宽度和高度设置为 50x50。
DPI 比例可以在 UI 线程上使用:
var dpiScale = DisplayInformation.GetForCurrentView().LogicalDpi / 96f;