图形的奇怪行为.MeasureString在不同的分辨率

时间:2012-03-02 00:00:39

标签: c# .net graphics gdi+ resolution

我注意到不同分辨率下Graphics.MeasureString的奇怪行为。

对于默认分辨率(96x96),我测试的不同字体大小之间存在线性关系。

然而,如果我把它提升到512 x 512,线性关系就会消失,使用测量字符串时会发生一些奇怪的事情。 (见下面的4个图)

如果我将分辨率保留为图形对象的默认大小,并测量字体大小,则这是字体大小与字符串宽度之间的关系:

图形对象,默认分辨率(96):

字体大小(X轴),特定字符串的WIDTH(Y轴) Width96

字体大小(X轴),特定字符串的高度(Y轴) Height96

但是,如果我更改分辨率

图形对象,512分辨率:

字体大小(X轴),特定字符串的WIDTH(Y轴) enter image description here

字体大小(X轴),特定字符串的高度(Y轴) enter image description here

任何人都知道为什么会发生这种情况?

谢谢你。

应该注意到我使用的是.NET 4(完整配置文件)

用于生成图表的代码(更改每种类型的分辨率):

string str = "6  CN-3 Tie EomgVeo405- 2ss>era09rni IBne 20iopv Atdrsn - Ng72";
SizeF sizef = new SizeF(855, 14.000001f);
StringFormat stringFormat = new StringFormat() 
{
    Alignment = StringAlignment.Center,
    LineAlignment = StringAlignment.Near,
    Trimming = StringTrimming.None,
    FormatFlags = StringFormatFlags.NoClip,
};

Bitmap b = new Bitmap(901, 401);
//b.SetResolution(512, 512);
Graphics g = Graphics.FromImage(b);

for (float x = origFont.Size; x >= 0.5; x -= 0.1f)
{
    var data = g.MeasureString(str, new Font("Microsoft Sans Serif", x), sizef, stringFormat);
    Console.WriteLine(x + "\t" + data.Width + "\t" + data.Height);
}

2 个答案:

答案 0 :(得分:1)

这个答案是猜测,但证据非常适合。

你看到的是被包裹在两行上的字符串。

我们假设以下内容:

  1. 文本的宽度与fontsize
  2. 成线性比例
  3. 文本的高度与fontsize
  4. 成线性比例

    这适合512分辨率图形的开始,一切都线性增加。

    在某些时候,宽度会急剧减少一定量,同时高度增加一倍。

    这意味着一个单词被移动到第2行,它将高度加倍(2行与之前的1行),并且由于该行的最后一个单词现在位于行的开头,所以该字符串的宽度变小了一些2。

    从那时起,宽度再次缓慢增加,因为字符串的部分仍然在第1行线性地随着字体大小的增加而变宽。与此同时,高度线性增加,但现在是休息前的两倍,因为2线现在变得更高,而之前是1。

    在某些时候,第1行的最后一个单词再次突破最大宽度,并在第2行向下移动,之前单独存在于该单词之前,此时,宽度再次急剧下降量。

    如果您要继续使用图表,我预测宽度将继续其当前模式。它每次下降的确切数量与被移动的单词的宽度成比例。同时,在某些时候,第二条线需要被打破,在这种情况下,你得到3倍的高度,然后高度将以3倍的速度增加,依此类推。

答案 1 :(得分:1)

我相信这可能会因为GDI +中的提示/网格拟合算法而发生。测试中的字体大小在字形易读性方面非常小,因此,渲染引擎会尝试对每个字形应用特殊转换以使其更清晰。这些转换在很大程度上取决于目标DPI。

值得一提的是,字体大小的大幅增加将导致更“线性”的依赖。

这个article通过一些例子更详细地解释了这些机制。

与此同时,您可以尝试修改Graphics.TextRenderingHint属性和/或尝试使用TextRenderer代替Graphics.DrawString,如果这样可以帮助您解决问题。