繁体   English   中英

WinRT:如何确保在画布上以像素完美的方式绘制图像?

[英]WinRT: How do I ensure Images are drawn in a pixel-perfect way on a Canvas?

我在Windows运行时环境中将图像实例添加到Canvas中,并且在140和180的缩放分辨率显示中,图像不断放大,缩放分辨率为100时看起来很完美。我尝试创建3个PNG图像,每个缩放尺寸一个:100 ,140、180,但仍会按比例放大它们,并且看起来模糊。 我在青色背景上创建了一个具有4个黑色像素的测试图像,并从模拟器中截取了屏幕截图,看看图像是如何模糊的,我的原始图像只有4个完美的黑色像素:

模糊,相信我

我尝试更改Image对象的拉伸模式,但无济于事。 我正在使用以下代码在运行时添加图像:

var bitmapImage = new BitmapImage();
StorageFile bitmapFile = await StorageFile.GetFileFromApplicationUriAsync(imageUri);
await bitmapImage.SetSourceAsync(await bitmapFile.OpenReadAsync());

Image image = new Image{ Source = bitmapImage};
image.SetValue(Canvas.LeftProperty, x);
image.SetValue(Canvas.TopProperty, y);
canvas.Children.Add(image);

如何获得图像以在画布中完美绘制像素,而无需缩放并以所需的确切x / y坐标?

我认为我有一种解决方法,但是它需要两个步骤:

首先,我必须使用一种更标准的方式来加载图像,而不涉及像这样获取文件路径。

var bitmapImage = new BitmapImage(imageUri);

某种程度上,这必须在内部保留更多信息,即该图像来自具有当前显示的相应ResolutionScale的文件。 因此,当它由画布绘制时,它根本不会缩放。 但是,这只能解决一半的问题。

下一个问题是用于指定在何处绘制图像的x,y坐标已缩放,因此将图像绘制在错误的位置,而不是我想要的位置。 我唯一能做的就是首先对它们进行缩放,如下所示:

var resScale = DisplayInformation.GetForCurrentView().ResolutionScale;
Image image = new Image{ Source = bitmapImage};
image.SetValue(Canvas.LeftProperty, (x * 100.0) / (int)resScale);
image.SetValue(Canvas.TopProperty, (y * 100.0) / (int)resScale);
canvas.Children.Add(image);

整个过程似乎有些疯狂,但到目前为止它似乎仍然有效……任何人都有更好的解决方案或解释,为什么所有这些都是必要的? 似乎Canvas类需要一种不缩放的模式,该模式不会弄乱图像或在不同分辨率的显示器上进行坐标调整。

更新 :这不是完美的工作,使用双精度值来存储值会导致精度损失,有时还会出现抗锯齿现象。 如果您想要像素完美的图形,这是不可接受的。 我仍在寻找完美的解决方案。

还有其他一些事情可能会对您的解决方案有所帮助。

  1. 在图像上使用UseLayoutRounding="False"
  2. 将“ Canvas放入全屏Viewbox ,然后将“ Canvas WidthHeight设置为屏幕分辨率。 在这种情况下,您将使用未缩放的Canvas.Left / Top值。
  3. 使用Direct2D / Direct3D进行渲染。

祝好运。

您可以将Stretch属性更改为"None" ,如果图像仍然网格化:

您应该查看保存在什么DPI上。 WPF试图独立于DPI,因此它试图在每个大小相同的监视器上绘制5“ x5”的图像。 即使分辨率更高,它仍应为5“ x5”,只有高分辨率才能以更高的质量渲染(光栅化)图像。

这是一些信息: http : //www.wpflearningexperience.com/? p= 41

如何将WPF大小转换为物理像素?

这是一段xaml代码

您可以随时使用从后面的代码进行缩放变换,以将图像缩放到适当的数量,无论其大小如何。

<Image  Canvas.Left="150"  Height="170" Width="170" Visibility="Visible" Stretch="None">
                <Image.Source >
                    <BitmapImage UriSource="ms-appx:///Assets/rollingDieSprite.png"></BitmapImage>
                </Image.Source>

                <Image.RenderTransform>
                    <ScaleTransform ScaleX="4" ScaleY="4" x:Name="scaleTfDie"></ScaleTransform>
                </Image.RenderTransform>
            </Image>

在后面的C#代码中,您可以进行以下操作

ScaleTransform sc = new ScaleTransform();
            sc.ScaleX = 0.9;
            sc.ScaleY = 0.9;
            imgDieRolling.RenderTransform = sc;

这将控制缩放。 尝试使用fill = none。 让我知道它是否有效。

我发现这个问题也很成问题。 我正在创建自定义位图,并将其绘制在画布上的不同位置。 我在XAML中找不到方法,但是我发现了使用Direct2D的方法。 设置D2DContext时,有一个名为SetUnitMode()的函数。 默认的单位模式是“ DIPS”,这会导致所有图形缩放。 通过切换到PIXELS模式,系统将停止按比例缩放图形,并按1:1的比例完成所有操作。

m_d2dContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM