【发布时间】:2013-07-31 22:51:07
【问题描述】:
首先让我说我已经对此进行了广泛的搜索,并找到了部分答案,但没有任何解决办法。
我需要在我的 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 并没有什么意义,因为图像根本不应该被缩放。
永远感谢任何能对此有所了解的人。
【问题讨论】:
-
只是出于好奇,因为我不理解
factor参数。打电话给pnlOutermost.LayoutTransform = new MatrixTransform(PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice)还不够吗?注意TransformFromDevice中的 From。当我将该变换应用到 WPF 应用程序的顶部网格时,它会“缩小”到标准的 96 dpi 或 100%。当然,这并不能解决您的对齐问题。 -
@Clemens,在你回到 1.0 之后,factor 参数可以支持额外的规模。因此,如果您发送 1.0,无论 DPI 如何,您都将返回 1-1 映射。如果您通过 1.25,您将获得该比例,而不必担心操作系统缩放的影响。
标签: wpf image xaml bitmap layouttransform