简体   繁体   English

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

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

I am adding Image instances to a Canvas in Windows Runtime environment and my image keeps getting scaled up when in 140 and 180 scale resolution displays, it looks perfect in scale resolution 100. I tried creating 3 PNG images, one for each scale size: 100, 140, 180 but it still scales them up and they look blurry. 我在Windows运行时环境中将图像实例添加到Canvas中,并且在140和180的缩放分辨率显示中,图像不断放大,缩放分辨率为100时看起来很完美。我尝试创建3个PNG图像,每个缩放尺寸一个:100 ,140、180,但仍会按比例放大它们,并且看起来模糊。 I created a test image with 4 black pixels on a cyan background and I took a screenshot from the simulator, see how the image is blurry, my original image has just 4 perfect black pixels: 我在青色背景上创建了一个具有4个黑色像素的测试图像,并从模拟器中截取了屏幕截图,看看图像是如何模糊的,我的原始图像只有4个完美的黑色像素:

模糊,相信我

I tried changing the stretch mode of my Image objects, but it does nothing. 我尝试更改Image对象的拉伸模式,但无济于事。 I'm using this code to add the images at runtime: 我正在使用以下代码在运行时添加图像:

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);

How do I get the images to draw pixel perfectly in the canvas without scaling and at the exact x/y coordinates I want? 如何获得图像以在画布中完美绘制像素,而无需缩放并以所需的确切x / y坐标?

I think I have a workaround, but it requires two steps: 我认为我有一种解决方法,但是它需要两个步骤:

First I have to load the image using a more a standard way that doesn't involve getting the file path like so. 首先,我必须使用一种更标准的方式来加载图像,而不涉及像这样获取文件路径。

var bitmapImage = new BitmapImage(imageUri);

Somehow this must retain more information internally that this image came from a file with the corresponding ResolutionScale for the current display. 某种程度上,这必须在内部保留更多信息,即该图像来自具有当前显示的相应ResolutionScale的文件。 Thus when it is drawn by the canvas it is not scaled at all. 因此,当它由画布绘制时,它根本不会缩放。 However this only solves half the problem. 但是,这只能解决一半的问题。

The next problem is that the x, y coordinates used to specify where the image is drawn are being scaled so the image is drawn in the wrong place, further than where I wanted. 下一个问题是用于指定在何处绘制图像的x,y坐标已缩放,因此将图像绘制在错误的位置,而不是我想要的位置。 The only thing I can figure to do is unscale them first like so: 我唯一能做的就是首先对它们进行缩放,如下所示:

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);

The whole thing seems a bit crazy but it seems to work so far... Anyone have a better solution or an explanation why all this is necessary? 整个过程似乎有些疯狂,但到目前为止它似乎仍然有效……任何人都有更好的解决方案或解释,为什么所有这些都是必要的? Seems like the Canvas class needs an unscaled mode that doesn't mess with the images or coordinates across different resolution displays. 似乎Canvas类需要一种不缩放的模式,该模式不会弄乱图像或在不同分辨率的显示器上进行坐标调整。

UPDATE : This doesn't work perfectly, using a double to store the value results in precision loss and sometimes there are anti-aliasing artifacts. 更新 :这不是完美的工作,使用双精度值来存储值会导致精度损失,有时还会出现抗锯齿现象。 This is not acceptable if you want pixel perfect graphics. 如果您想要像素完美的图形,这是不可接受的。 I am still looking for a perfect solution. 我仍在寻找完美的解决方案。

There are a few more things that might help with your solution. 还有其他一些事情可能会对您的解决方案有所帮助。

  1. Use UseLayoutRounding="False" on your image. 在图像上使用UseLayoutRounding="False"
  2. Put your Canvas in a full-screen Viewbox , then set the Canvas Width and Height to the screen resolution. 将“ Canvas放入全屏Viewbox ,然后将“ Canvas WidthHeight设置为屏幕分辨率。 You'd use unscaled Canvas.Left / Top values in this case. 在这种情况下,您将使用未缩放的Canvas.Left / Top值。
  3. Use Direct2D/Direct3D for rendering. 使用Direct2D / Direct3D进行渲染。

Good luck. 祝好运。

You can change the Stretch property to "None" , If you image is still meshed-up: 您可以将Stretch属性更改为"None" ,如果图像仍然网格化:

You should look at what DPI it is saved on. 您应该查看保存在什么DPI上。 WPF tries to be DPI-independend, so it tries to draw an image of 5"x5" on every monitor the same size. WPF试图独立于DPI,因此它试图在每个大小相同的监视器上绘制5“ x5”的图像。 Even when the resolution is higher, it still should be 5"x5" only a high resolution would render(rasterize) the image in higher quality. 即使分辨率更高,它仍应为5“ x5”,只有高分辨率才能以更高的质量渲染(光栅化)图像。

Here's some info: http://www.wpflearningexperience.com/?p=41 这是一些信息: http : //www.wpflearningexperience.com/? p= 41

How do I convert a WPF size to physical pixels? 如何将WPF大小转换为物理像素?

Here's a piece of xaml code 这是一段xaml代码

you can always use scale transform from code behind to scale the images to appropriate amount be it less or more. 您可以随时使用从后面的代码进行缩放变换,以将图像缩放到适当的数量,无论其大小如何。

<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>

in c# code behind you can go for the following 在后面的C#代码中,您可以进行以下操作

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

this will control the scaling . 这将控制缩放。 try using fill=none . 尝试使用fill = none。 Let me know if it works. 让我知道它是否有效。

I found this issue quite problematic as well. 我发现这个问题也很成问题。 I'm creating custom bitmaps and drawing them at different positions on the canvas. 我正在创建自定义位图,并将其绘制在画布上的不同位置。 I couldn't find a way in the XAML, but I found a way using Direct2D. 我在XAML中找不到方法,但是我发现了使用Direct2D的方法。 When you set up your D2DContext, there's a function called SetUnitMode(). 设置D2DContext时,有一个名为SetUnitMode()的函数。 The default unit mode is "DIPS" which causes all drawing to be scaled. 默认的单位模式是“ DIPS”,这会导致所有图形缩放。 By switching to PIXELS mode, the system stops scaling the drawing and does everything 1:1. 通过切换到PIXELS模式,系统将停止按比例缩放图形,并按1:1的比例完成所有操作。

m_d2dContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS);

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

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