You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 跨平台测量字符串像素宽度并匹配System.Drawing.Common结果

问题根因

测量结果差异来自两个核心配置不匹配:

  • System.Drawing.Common的Graphics.MeasureString默认使用兼容GDI的排版规则,会在字符串前后额外添加约1/6em的留白用于字符悬挂,同时默认开启字符间距适配,并非纯粹的字符边界宽度
  • SkiaSharp、ImageSharp默认使用印刷业标准的紧凑测量规则,仅计算字符本身的实际占用宽度,没有额外留白

如果你可以调整原有System.Drawing的测量逻辑,直接添加StringFormat.GenericTypographic参数即可让输出和两个跨平台库的251px左右结果对齐,代码示例:

var text = "abc123 this is some long text my dog's name is fido.";
using (var bitmap = new Bitmap(500, 50))
using (var graphics = Graphics.FromImage(bitmap))
{
    using var font = new System.Drawing.Font(familyName: "Times New Roman", emSize: 9f);
    // 增加这一行使用标准印刷排版规则,去掉额外留白
    var format = StringFormat.GenericTypographic;
    var ms = graphics.MeasureString(text, font, int.MaxValue, format);
    Console.WriteLine($"'{text}' via System.Drawing: {ms.Width} x {ms.Height}");
}

如果你必须让跨平台库匹配原有System.Drawing的默认394px左右的输出结果,可分别调整两个库的配置:

SkiaSharp 适配方案

var text = "abc123 this is some long text my dog's name is fido.";
using (var paint = new SKPaint())
{
    paint.Typeface = SKTypeface.FromFamilyName("Times New Roman");
    paint.TextSize = 12f; // 9磅=9*96DPI/72=12px,该换算规则正确
    paint.TextAlign = SKTextAlign.Left;
    paint.HintingLevel = SKHintingLevel.Full;
    // 模拟GDI+默认添加的前后留白:左右各加1/6em的宽度
    var em = paint.TextSize / paint.Typeface.UnitsPerEm * paint.Typeface.CapHeight;
    var extraPadding = em / 6 * 2;
    var skBounds = SKRect.Empty;
    paint.MeasureText(text.AsSpan(), ref skBounds);
    // 补充留白后得到与原System.Drawing一致的宽度
    var finalWidth = skBounds.Width + extraPadding;
    Console.WriteLine($"'{text}' via SkiaSharp: {finalWidth} x {skBounds.Height}");
}

ImageSharp 适配方案

var text = "abc123 this is some long text my dog's name is fido.";
var imgSharpFont = SixLabors.Fonts.SystemFonts.CreateFont("Times New Roman", 12f);
// 配置GDI兼容排版模式
var options = new RendererOptions(imgSharpFont)
{
    ApplyKerning = true,
    DpiX = 96,
    DpiY = 96,
    TextLayoutMode = TextLayoutMode.Gdi
};
var imgSharpMeasurement = TextMeasurer.Measure(text, options);
Console.WriteLine($"'{text}' via ImageSharp: {imgSharpMeasurement.Width} x {imgSharpMeasurement.Height}");

内容的提问来源于stack exchange,提问作者Jon Sagara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 14:24:03