首先让我说我已经对此进行了广泛的搜索并找到了部分答案,但没有任何方法可以奏效。
我需要在我的 WPF 应用程序中显示未缩放的位图图像。我想将位图的 1 个像素映射到显示器的 1 个像素。我确实打算通过发送多个版本的位图来支持多种分辨率。But I want to know that, when a particular bitmap has been chosen, it will be rendered EXACTLY as it has been designed.
我克服 WPF 中发生的自动缩放的策略是查看自动应用的内容(通过 OS DPI 设置),然后将相反的 LayoutTransform 应用到我的窗口的最外层容器。
这可确保无论用户的 DPI 设置是什么,应用程序都会以 1:1 的 WPF 像素与硬件像素的比率呈现窗口内容。到目前为止,一切都很好。
该代码看起来像这样。(假设这是使用参数 1.0 调用的)。
private void SetScale(double factor)
{
// First note the current window transform factor.
// This is the factor being applied to the entire window due to OS DPI settings.
Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
double currentWindowTransformFactorX = m.M11;
double currentWindowTransformFactorY = m.M22;
// Now calculate the inverse.
double currentWindowTransformInverseX = (1 / m.M11);
double currentWindowTransformInverseY = (1 / m.M22);
// This factor will put us "back to 1.0" in terms of a device-independent-pixel to physical pixel mapping.
// On top of this, we can apply our caller-specified factor.
double transformFactorX = currentWindowTransformInverseX * factor;
double transformFactorY = currentWindowTransformInverseY * factor;
// Apply the transform to the registered target container
ScaleTransform dpiTransform = new ScaleTransform(transformFactorX, transformFactorY);
if (dpiTransform.CanFreeze)
dpiTransform.Freeze();
this.pnlOutermost.LayoutTransform = dpiTransform;
}
到这里为止,一切都很好。无论我将我的 Windows DPI 设置为什么,该主容器的内容总是完全相同的大小,并且位图被精确渲染。
有趣的来了。我想通过提供特定分辨率的艺术作品来支持不同的屏幕分辨率,并适当地缩放我的整个 UI。
事实证明 LayoutTransform 非常适合这个。因此,如果我用 1.25 或 1.5 或其他任何值调用上述方法,则整个 UI 会缩放,并且一切看起来都很完美……除了我的图像,即使我将源更改为图像完全适合新的缩放尺寸。
例如,假设我在 XAML 中有一个 100x100 的图像。我的作品有三种风格:100x100、125x125 和 150x150。当我缩放容纳图像的容器时,我还将该图像的源更改为适当的源。
有趣的是,如果图像对象所在的位置在按因子缩放时会产生积分结果,那么缩放后的图像看起来很好。也就是说,假设图像具有以下属性:
Canvas.Left = 12
Canvas.Top = 100
当我们应用 1.25 的因子时,得到 15 和 125,图像看起来很棒。但是如果图像移动了一个像素,就说:
Canvas.Left = 13
Canvas.Top = 100
现在,当我们应用 1.25 的因子时,我们得到 15.25 和 125,结果看起来很糟糕。
显然,这看起来像是某种舍入问题或类似问题。所以我试过:
UseLayoutRounding="True"
SnapsToDevicePixels="True"
RenderOptions.EdgeMode="Aliased"
RenderOptions.BitmapScalingMode="NearestNeighbor"
我已经在窗口、正在缩放的容器和图像对象中尝试了这些。没有任何效果。无论如何,BitmapScalingMode 并没有真正的意义,因为图像根本不应该被缩放。
永远感谢任何能对此有所了解的人。