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

iText7中TextRenderInfo.GetFontSize()返回错误值的排查与解决

PDF文本提取中字号返回1的原因及解决方案

问题背景

使用iText 7提取PDF文本时,4个测试PDF里有3个返回字号值为1,仅1个能获取正确字号;此前使用iTextSharp 5.5.13时可正常获取正确字号。相关代码及尝试的方法如下:

原提取代码

using System.Text;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas.Parser;
using iText.Kernel.Pdf.Canvas.Parser.Data;
using iText.Kernel.Pdf.Canvas.Parser.Listener;

namespace PDFTextExtraction
{
    class Program
    {
        static void Main(string[] args)
        {
            string pdfFilePath = "pathtopdf.pdf";

            using (PdfReader pdfReader = new PdfReader(pdfFilePath))
            {
                using (PdfDocument pdfDocument = new PdfDocument(pdfReader))
                {
                    MyTextEventListener listener = new MyTextEventListener();

                    for (int pageNum = 1; pageNum <= pdfDocument.GetNumberOfPages(); pageNum++)
                    {
                        PdfPage page = pdfDocument.GetPage(pageNum);
                        PdfCanvasProcessor parser = new PdfCanvasProcessor(listener);
                        parser.ProcessPageContent(page);
                    }

                    Console.WriteLine("提取的文本及字体信息:");
                    Console.WriteLine(listener.GetExtractedText());
                }
            }
        }
    }

    public class MyTextEventListener : IEventListener
    {
        private readonly StringBuilder extractedText = new StringBuilder();

        public void EventOccurred(IEventData data, EventType type)
        {
            if (type.Equals(EventType.RENDER_TEXT))
            {
                TextRenderInfo renderInfo = (TextRenderInfo)data;
                string text = renderInfo.GetText();
                string font = renderInfo.GetFont().GetFontProgram().ToString();
                float fontSize = renderInfo.GetFontSize();

                extractedText.AppendLine($"文本: {text} | 字体: {font} | 字号: {fontSize}");
            }
        }

        public ICollection<EventType> GetSupportedEvents()
        {
            return new List<EventType> { EventType.RENDER_TEXT };
        }

        public string GetExtractedText()
        {
            return extractedText.ToString();
        }
    }
}

已尝试的方法

float ascent = renderInfo.GetAscentLine().GetStartPoint().Get(1);
float descent = renderInfo.GetDescentLine().GetStartPoint().Get(1);
float fontSize = ascent - descent;

相关PDF操作符示例

BT 
0 0.6 0.95 0 k 
/GS0 gs 
/T1_0 1 Tf 
0.024 Tc 
-0.024 Tw 
8 0 0 8 32.3386 171.361 Tm
[(V)43.2(o)2.2(r)-1(n)1.5(ame)24( Na)7.9(c)-1.4(h)-1.1(n)1.4(a)0.5(me)] TJ
ET

实际正确字号应为8pt,疑问:Tf里的1是字号吗?通过文本矩阵计算字号的方法是否可行?


原因分析

  1. PDF排版机制差异:在你提供的PDF操作符中,T1_0 1 Tf是设置字体和原始字号参数(这里的1是Tf操作符的字号值),但后续的8 0 0 8 32.3386 171.361 Tm是文本矩阵操作,其中前两个8分别是X、Y方向的缩放因子。实际显示字号是Tf的字号值 × 文本矩阵的缩放因子,即1×8=8pt。
  2. iText版本行为变更:iTextSharp 5.5.13会自动结合Tf的字号值和文本矩阵的缩放因子,返回实际显示的字号;而iText 7的GetFontSize()仅返回Tf操作符中的原始字号值(即1),不会自动应用文本矩阵的缩放。
  3. PDF生成工具的排版习惯:很多PDF生成工具为了排版灵活,会将Tf的字号设为1,再通过文本矩阵的缩放来控制实际显示大小,这就导致GetFontSize()拿到的是原始值1,而非实际显示的字号。

解决方案

1. 通过文本矩阵计算实际字号(推荐)

你提到的方法是可行的,更准确的方式是取文本矩阵的Y方向缩放值(因为PDF中字体的大小对应Y轴方向的缩放),代码示例:

Matrix textMatrix = renderInfo.GetTextMatrix();
// 取Y方向缩放因子,绝对值处理防止翻转情况
float actualFontSize = Math.Abs(textMatrix.Get(Matrix.I22));

如果遇到非均匀缩放(X和Y缩放值不同),可根据需求取最大值或平均值:

float scaleX = Math.Abs(textMatrix.Get(Matrix.I11));
float scaleY = Math.Abs(textMatrix.Get(Matrix.I22));
float actualFontSize = Math.Max(scaleX, scaleY);
// 或取平均值:float actualFontSize = (scaleX + scaleY) / 2;

2. 通过字体 ascent/descent 计算实际字号

你之前尝试的方法可以优化,通过计算ascent和descent线的Y坐标差,得到实际显示的字体高度(即视觉字号):

LineSegment ascentLine = renderInfo.GetAscentLine();
LineSegment descentLine = renderInfo.GetDescentLine();
// 计算Y坐标差,绝对值处理防止翻转
float actualFontSize = Math.Abs(ascentLine.GetStartPoint().Get(1) - descentLine.GetStartPoint().Get(1));

这个方法不受缩放是否均匀的影响,能直接得到视觉上的字号大小。

3. 兼容旧版本行为

如果需要和iTextSharp 5.5.13的行为一致,可在获取GetFontSize()后,结合文本矩阵的缩放因子计算:

float rawFontSize = renderInfo.GetFontSize();
Matrix textMatrix = renderInfo.GetTextMatrix();
float scaleY = Math.Abs(textMatrix.Get(Matrix.I22));
float actualFontSize = rawFontSize * scaleY;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:17:07