[英]Highlight words in a pdf using itextsharp, not displaying highlighted word in browser
使用itextsharp在浏览器中不显示突出显示的单词。
土坯
浏览器
码
List<iTextSharp.text.Rectangle> 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<iTextSharp.text.Rectangle> 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的代码中存在一个问题,就是要在他使用的路径中添加一个矩形
canvas.Rectangle(rect);
不幸的是,这不是他所期望的: Rectangle
类具有多个属性,而不仅仅是矩形的坐标,有关所选边框,边框颜色和内部颜色的最重要信息, PdfContentByte.Rectangle(Rectangle)
根据这些属性绘制矩形。
但是,在当前情况下, rect
仅用于传输矩形的坐标,因此那些附加属性均为false
或null
。 因此, canvas.Rectangle(rect)
什么都不做!
相反,OP应该使用
canvas.Rectangle(rect.Left, rect.Bottom, rect.Width, rect.Height);
这里。
此外 ,@ Bruno在回答中提到
请注意,如果将黄色矩形添加为不透明形状(例如,在图像下方),则不会看到黄色矩形。
不幸的是,这里确实是这种情况:该文档实际上是一个扫描的文档,每页都是一个页面填充图像,在该图像下绘制了等效的文本(可能在OCR之后),以允许进行文本复制和粘贴。
因此,无论OP的代码可以在UnderContent
,它都会被该图像隐藏。
因此,让我们尝试一些不同的东西...
@Bruno在他的回答中也指出了这种情况的解决方案:
在这种情况下,您可以在现有内容之上添加一个透明矩形。
遵循此建议,我们将替换
canvas = stamper.GetUnderContent(pageno);
通过
canvas = stamper.GetOverContent(pageno);
PdfGState state = new PdfGState();
state.FillOpacity = .3f;
canvas.SetGState(state);
在第三个文档页面上选择“支持”一词,我们得到:
黄色在这里很苍白。
使用.6
的Opacity
值代替
现在,黄色更加强烈,但文字开始变淡。
对于这样的任务,我实际上更喜欢使用混合模式Darken 。 这可以通过使用
state.BlendMode = new PdfName("Darken");
而不是state.FillOpacity = .3f
。 这导致
这海事组织看起来更好。
OP评论
客户提供了pdf文件。 这样,他们突出显示了文本,突出显示的文本显示在浏览器中
客户端的PDF实际上使用注释,就像其原始代码中的OP一样,但是相反,客户端的每个注释都包含一个外观流,而iText生成的高亮注释则没有。
提供外观是可选的,并且如果没有给出,则PDF查看器确实应该生成外观。 但是,显然,有许多PDF查看器依赖于PDF带来的外观。
顺便说一句,客户端PDF中的外观实际上使用混合模式Multiply 。 对于基础白色和黑色,“ 变暗”和“ 相乘”具有相同的结果。
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);
但它不起作用。
他尝试中遇到的问题是:
因此,以下代码显示了如何执行此操作。
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<iTextSharp.text.Rectangle> 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查看器都支持该功能。
如果要在每个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()
等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.