使用iText7与C#高亮PDF文字时位置偏移问题求助
问题原因
- 坐标系统不匹配:PDF页面可能存在旋转(如90/180/270度),
RegexBasedLocationExtractionStrategy返回的文本位置矩形是基于内容流的原始用户空间坐标,未适配页面旋转后的坐标系统,导致绘制位置偏移。 - 绘制顺序错误:你使用
NewContentStreamAfter()在原有文本内容之后绘制红色背景,会导致红色覆盖文本,而不是作为背景显示。
解决方案
修改代码解决坐标适配和绘制顺序问题:
- 将画布创建改为
NewContentStreamBefore(),让背景绘制在文本下方; - 根据页面旋转角度,转换文本位置矩形的坐标,适配页面的显示坐标系统;
- 补充
System.Text.RegularExpressions引用(原代码使用了Regex但未显式引用)。
修改后的完整代码
using iText.Kernel.Colors; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas; using iText.Kernel.Pdf.Canvas.Parser; using iText.Kernel.Pdf.Canvas.Parser.Listener; using System.IO; using System.Text.RegularExpressions; using System.Collections.Generic; FileStream src = new FileStream("C:\\Temp\\34207180.pdf", FileMode.Open); MemoryStream ms = new MemoryStream(); string keyword = "and"; PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(ms)); int pdfPages = pdfDoc.GetNumberOfPages(); for (int page = 1; page <= pdfPages; page++) { Regex regex = new Regex(keyword, RegexOptions.IgnoreCase); RegexBasedLocationExtractionStrategy extractionStrategy = new RegexBasedLocationExtractionStrategy(regex); PdfCanvasProcessor parser = new PdfCanvasProcessor(extractionStrategy); PdfPage pdfPage = pdfDoc.GetPage(page); parser.ProcessPageContent(pdfPage); List<IPdfTextLocation> locs = extractionStrategy.GetResultantLocations().ToList(); // 创建在文本内容之前的画布,用于绘制背景 PdfCanvas pdfCanvas = new PdfCanvas(pdfPage.NewContentStreamBefore(), pdfPage.GetResources(), pdfDoc); Rectangle pageSize = pdfPage.GetPageSizeWithRotation(); int rotation = pdfPage.GetRotation(); foreach (var l in locs) { Rectangle rect = l.GetRectangle(); Rectangle transformedRect; // 根据页面旋转转换坐标 switch (rotation) { case 90: transformedRect = new Rectangle( pageSize.GetHeight() - rect.GetY() - rect.GetHeight(), rect.GetX(), rect.GetHeight(), rect.GetWidth() ); break; case 180: transformedRect = new Rectangle( pageSize.GetWidth() - rect.GetX() - rect.GetWidth(), pageSize.GetHeight() - rect.GetY() - rect.GetHeight(), rect.GetWidth(), rect.GetHeight() ); break; case 270: transformedRect = new Rectangle( rect.GetY(), pageSize.GetWidth() - rect.GetX() - rect.GetWidth(), rect.GetHeight(), rect.GetWidth() ); break; default: transformedRect = rect; break; } pdfCanvas .SaveState() .SetFillColor(ColorConstants.RED) .Rectangle(transformedRect.GetX(), transformedRect.GetY(), transformedRect.GetWidth(), transformedRect.GetHeight()) .Fill() .RestoreState(); } } pdfDoc.Close(); byte[] img = ms.ToArray(); File.WriteAllBytes("C:\\Temp\\34207180-dest.pdf", img);
额外说明
- 如果页面存在裁剪框(CropBox)偏移,还需要结合
pdfPage.GetCropBox()进一步调整坐标,但大多数常规PDF仅需处理旋转即可解决位置问题; RegexOptions.IgnoreCase确保匹配大小写不同的"and"(如"And"、"AND"),若不需要可移除该选项。
内容的提问来源于stack exchange,提问作者Adam D.
相关产品推荐
相关产品推荐

