使用itextsharp突出显示pdf中的单词,而不是在浏览器中显示突出显示的单词

使用itextsharp在浏览器中不显示突出显示的单词。

土砖

在此处输入图像描述

浏览器

在此处输入图像描述

List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { float[] quad = { rect.Left - 3.0f, rect.Bottom, rect.Right, rect.Bottom, rect.Left - 3.0f, rect.Top + 1.0f, rect.Right, rect.Top + 1.0f }; //Create our hightlight PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quad); //Set the color highlight.Color = BaseColor.YELLOW; //Add the annotation stamper.AddAnnotation(highlight, pageno); } 

请帮我解决这个问题。

更新代码

  private void highlightPDF() { //Create a simple test file string outputFile = Server.MapPath("~/pdf/16193037V_Dhana-FI_NK-QA_Completed.pdf"); string filename = "HL" + Convert.ToString(Session["Filename"]) + ".pdf"; Session["Filename"] = "HL" + Convert.ToString(Session["Filename"]); //Create a new file from our test file with highlighting string highLightFile = Server.MapPath("~/pdf/" + filename); //Bind a reader and stamper to our test PDF PdfReader reader = new PdfReader(outputFile); iTextSharp.text.pdf.PdfContentByte canvas; int pageno = Convert.ToInt16(txtPageno.Text); using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None)) { using (PdfStamper stamper = new PdfStamper(reader, fs)) { canvas = stamper.GetUnderContent(pageno); myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy(); strategy.UndercontentCharacterSpacing = canvas.CharacterSpacing; strategy.UndercontentHorizontalScaling = canvas.HorizontalScaling; string currentText = PdfTextExtractor.GetTextFromPage(reader, pageno, strategy); string text = txtHighlight.Text.Replace("\r\n", "").Replace("\\n", "\n").Replace(" ", " "); string[] splitText = text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < splitText.Length; i++) { List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { canvas.SaveState(); canvas.SetColorFill(BaseColor.YELLOW); canvas.Rectangle(rect); canvas.Fill(); canvas.RestoreState(); } } } } reader.Close(); } 

它没有突出显示文本。 我通过了文本和页面no来突出显示文本。

首先…

为什么OP的(更新的)代码不起作用

实际上有两个因素。

首先, OP的代码中存在一个问题,即在他使用的路径中添加一个矩形

 canvas.Rectangle(rect); 

不幸的是,这并不是他所期望的: Rectangle类有超出矩形坐标的多个属性,最重要的是关于选定边框,边框颜色和内部颜色的信息, PdfContentByte.Rectangle(Rectangle)根据这些属性绘制一个矩形。

但是,在这种情况下, rect仅用于传输矩形的坐标,因此这些附加属性都是falsenull 。 因此, canvas.Rectangle(rect)什么都不做!

相反,OP应该使用

 canvas.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height); 

这里。

此外 ,@布鲁诺在他的回答中提到

请注意,如果将其添加到不透明形状(例如图像下方)下,则不会看到黄色矩形。

不幸的是,这就是这种情况:文档实际上是一个扫描文档,每个页面都是一个页面填充图像,在该图像下绘制等效文本(可能在OCR之后)以允许文本复制和粘贴。

因此,无论OP的代码如何在UnderContentUnderContent ,它都将被该图像隐藏。

因此,让我们尝试不同的东西……

如何使它工作

@Bruno在他的回答中也指出了这种情况的解决方案:

在这种情况下,您可以在现有内容的顶部添加透明矩形。

按照这个建议我们更换

 canvas = stamper.GetUnderContent(pageno); 

通过

 canvas = stamper.GetOverContent(pageno); PdfGState state = new PdfGState(); state.FillOpacity = .3f; canvas.SetGState(state); 

在我们得到的第三个文档页面上选择“支持”一词:

使用.3的不透明度

这里的黄色很苍白。

我们得到的Opacity值为.6

使用.6的不透明度

现在黄色更强烈但文字开始变得苍白。

对于这样的任务,我实际上更喜欢使用混合模式Darken 。 这可以通过使用来完成

 state.BlendMode = new PdfName("Darken"); 

而不是state.FillOpacity = .3f 。 这导致了

使用混合模式变暗

这个IMO看起来更好。

客户如何做到这一点

OP评论道

客户给出了pdf。 在那里,他们突出显示文本,突出显示的文本显示在浏览器中

客户端的PDF实际上使用注释,就像他原始代码中的OP一样,但相比之下,每个客户端的注释都包含一个外观流,iText生成的突出显示注释不包含。

提供外观是可选的,如果没有给出,PDF查看器确实应该生成外观。 显然,有许多PDF查看器依赖于PDF带来的外观。

顺便说一下,客户端PDF中的外观实际上使用了混合模式Multiply 。 对于底层的白色和黑色, DarkenMultiply具有相同的结果。

使其与注释一起使用

在评论中,OP想知道

还有一个疑问,如果用户错误地突出显示了如何去除黄色(或将黄色变为白色)? 我把黄色变成了白色,但它没有用。 canvas.SetColorFill(BaseColor.WHITE);

撤消对页面内容的更改通常比撤消添加注释更困难。 因此,让我们使OP的原始代码也起作用,即在高亮注释中添加外观流。

正如OP在另一条评论中报道的那样,他首次尝试添加外观流失败了:

 PdfAppearance appearance = PdfAppearance.CreateAppearance(stamper.Writer, rect.Width, rect.Height); appearance.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height); appearance.SetColorFill(BaseColor.WHITE); appearance.Fill(); highlight.SetAppearance( PdfAnnotation.APPEARANCE_NORMAL, appearance ); stamper.AddAnnotation(highlight, pageno); 

但它不起作用。

他尝试的问题是:

  • 外观模板的原点位于注释区域的左下角,而不是页面的左下角。 因此,要为相关区域着色,矩形的左下角必须为(0,0)。
  • 严格地说,必须开始路径构建之前设置颜色。
  • 应使用与白色不同的颜色进行突出显示。
  • 应使用透明度或适当的渲染模式,以允许原始的标记文本通过。

因此,以下代码显示了如何执行此操作。

 private void highlightPDFAnnotation(string outputFile, string highLightFile, int pageno, string[] splitText) { PdfReader reader = new PdfReader(outputFile); iTextSharp.text.pdf.PdfContentByte canvas; using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None)) { using (PdfStamper stamper = new PdfStamper(reader, fs)) { myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy(); strategy.UndercontentHorizontalScaling = 100; string currentText = PdfTextExtractor.GetTextFromPage(reader, pageno, strategy); for (int i = 0; i < splitText.Length; i++) { List MatchesFound = strategy.GetTextLocations(splitText[i].Trim(), StringComparison.CurrentCultureIgnoreCase); foreach (Rectangle rect in MatchesFound) { float[] quad = { rect.Left - 3.0f, rect.Bottom, rect.Right, rect.Bottom, rect.Left - 3.0f, rect.Top + 1.0f, rect.Right, rect.Top + 1.0f }; //Create our hightlight PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quad); //Set the color highlight.Color = BaseColor.YELLOW; PdfAppearance appearance = PdfAppearance.CreateAppearance(stamper.Writer, rect.Width, rect.Height); PdfGState state = new PdfGState(); state.BlendMode = new PdfName("Multiply"); appearance.SetGState(state); appearance.Rectangle(0, 0, rect.Width, rect.Height); appearance.SetColorFill(BaseColor.YELLOW); appearance.Fill(); highlight.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, appearance); //Add the annotation stamper.AddAnnotation(highlight, pageno); } } } } reader.Close(); } 

这些注释也由Chrome显示,并且作为注释,可以轻松删除它们。

您正在使用标记注释来突出显示文本。 那很棒! 你的代码和iText没有任何问题。 但是:并非所有PDF查看器都支持该function。

如果要在每个PDF查看器中查看突出显示的文本,(次优)解决方法可能是在现有内容的内容流中添加黄色矩形(假设现有内容不是不透明的)。

这在HighLightByAddingContent示例中进行了演示:

 public void manipulatePdf(String src, String dest) throws IOException, DocumentException { PdfReader reader = new PdfReader(src); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest)); PdfContentByte canvas = stamper.getUnderContent(1); canvas.saveState(); canvas.setColorFill(BaseColor.YELLOW); canvas.rectangle(36, 786, 66, 16); canvas.fill(); canvas.restoreState(); stamper.close(); reader.close(); } 

在这个例子中,我们获取一个名为hello.pdf的文件,然后添加一个黄色矩形,结果文件为hello_highlighted.pdf 。

请注意,如果将其添加到不透明形状(例如图像下方)下,则不会看到黄色矩形。 在这种情况下,您可以在现有内容的顶部添加透明矩形。

更新:我的例子是用Java编写的。 对于开发人员来说,将它移植到C#应该不是问题。 这只是将一些小案改为大案的问题。 例如stamper.GetUnderContent(1)而不是stamper.getUnderContent(1)canvas.saveState()而不是canvas.saveState() ,依此类推。