这个问题是我以前的问题的另一个版本: I want to get all objects except text object as an image from PDF using iTextSharp
我正在开发一个程序,用于使用iTextSharp出于特定原因将PDF转换为PPTX。到目前为止,我所做的是获取所有文本对象,图像对象和位置。但是我很难获得没有文本的矢量绘图(例如表格)。实际上,如果我可以将它们作为图像获得,那会更好。我的计划是将除文本对象之外的所有对象合并为背景图像,并将文本对象放置在适当的位置。我试图在这里找到类似的问题,但到目前为止还没有运气。如果有人知道如何完成这项工作,请回答。谢谢。
我已经阅读了许多相关的问题和讨论,并决定在此处询问其他版本。 我还有以下两个计划。如果iText开发人员/专家可以指导我,我将不胜感激。
public class MyLocationTextExtractionStrategy: IExtRenderListener, ITextExtractionStrategy,IElementListener
{
//Text
public List<RectAndText> myPoints_txt = new List<RectAndText>();
public List<RectAndImage> myPoints_img = new List<RectAndImage>();
public FieldInfo GsField = typeof(TextRenderInfo).GetField("gs", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
public FieldInfo MarkedContentInfosField = typeof(TextRenderInfo).GetField("markedContentInfos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
public FieldInfo MarkedContentInfoTagField = typeof(MarkedContentInfo).GetField("tag", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
PdfName EMBEDDED_DOCUMENT = new PdfName("EmbeddedDocument");
//Image
public List<byte[]> Images = new List<byte[]>();
public List<string> ImageNames = new List<string>();
public bool Add(IElement element)
{
element = element;
return true;
}
public void BeginTextBlock()
{
}
public void ClipPath(int rule)
{
}
public void EndTextBlock()
{
}
public string GetResultantText()
{
return "";
}
public void ModifyPath(PathConstructionRenderInfo renderInfo)
{
// ****************************************
// I think this point I can get info on Path
// ****************************************
}
public void RenderImage(ImageRenderInfo renderInfo)
{
PdfImageObject image = renderInfo.GetImage();
try
{
image = renderInfo.GetImage();
if (image == null) return;
ImageNames.Add(string.Format(
"Image{0}.{1}", renderInfo.GetRef().Number, image.GetFileType()
));
//Write Image to byte
using (MemoryStream ms = new MemoryStream(image.GetImageAsBytes()))
{
Images.Add(ms.ToArray());
}
Matrix matrix = renderInfo.GetImageCTM();
this.myPoints_img.Add(new RectAndImage(matrix[Matrix.I31], matrix[Matrix.I32], matrix[Matrix.I11], matrix[Matrix.I12], Images));
}
catch (Exception e)
{
}
}
public iTextSharp.text.pdf.parser.Path RenderPath(PathPaintingRenderInfo renderInfo)
{
// ****************************************
// I think this point I can get info on Path
// ****************************************
return null;
}
public void RenderText(TextRenderInfo renderInfo)
{
DocumentFont _font = renderInfo.GetFont();
LineSegment descentLine = renderInfo.GetDescentLine();
LineSegment ascentLine = renderInfo.GetAscentLine();
float x0 = descentLine.GetStartPoint()[0];
float x1 = ascentLine.GetEndPoint()[0];
float y0 = descentLine.GetStartPoint()[1];
float y1 = ascentLine.GetEndPoint()[1];
Rectangle rect = new Rectangle(x0,y0,x1,y1);
GraphicsState gs = (GraphicsState)GsField.GetValue(renderInfo);
float fontSize = gs.FontSize;
String font_color = gs.FillColor.ToString().Substring(14,6);
IList<MarkedContentInfo> markedContentInfos = (IList<MarkedContentInfo>)MarkedContentInfosField.GetValue(renderInfo);
if (markedContentInfos != null && markedContentInfos.Count > 0)
{
foreach (MarkedContentInfo info in markedContentInfos)
{
if (EMBEDDED_DOCUMENT.Equals(MarkedContentInfoTagField.GetValue(info)))
return;
}
}
this.myPoints_txt.Add(new RectAndText(rect, renderInfo.GetText(), fontSize,renderInfo.GetFont().PostscriptFontName, font_color));
}
}
1)我可以从PDF中删除所有文本对象,然后将其输出到新的文本对象吗? 如果是,我可以将输出的所有页面作为图像,并将它们用作PPTX的背景。 然后,我终于可以编写文本了(已经使用上面的代码使用ITextExtractionStrategy检索了文本)
2)如果1)不可能,我将从原始PDF中检索所有Path信息(使用IExtRenderListener)并将其绘制在新的Bitmap上。 最后,我可以将其作为背景,并在其上放置文本/图像。 在这种情况下,使用ModifyPath和RenderPath检索路径信息是正确的方法吗?
我知道这似乎有多个问题,但我认为最好在一个线程中全部编写以帮助理解。 我非常感谢您提出的任何提示或意见。
我相信@ mkl,@ Amine,@ Bruno Lowagie可以帮助我。 预先感谢。
答案 0 :(得分:2)
在my answer to your old question中,我解释了这些IExtRenderListener
回调方法的含义,因此基本上剩下的问题是
1)我可以从PDF中删除所有文本对象并将其输出到新的文本对象吗?
您可以使用this answer中的通用内容流编辑器类PdfContentStreamEditor
。像这样简单地从中得出
class TextRemover : PdfContentStreamEditor
{
protected override void Write(PdfContentStreamProcessor processor, PdfLiteral operatorLit, List<PdfObject> operands)
{
if (!TEXT_SHOWING_OPERATORS.Contains(operatorLit.ToString()))
{
base.Write(processor, operatorLit, operands);
}
}
List<string> TEXT_SHOWING_OPERATORS = new List<string> { "Tj", "'", "\"", "TJ" };
}
并像这样使用它
using (PdfReader pdfReader = new PdfReader(source))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(dest, FileMode.Create, FileAccess.Write), (char)0, true))
{
pdfStamper.RotateContents = false;
PdfContentStreamEditor editor = new TextRemover();
for (int i = 1; i <= pdfReader.NumberOfPages; i++)
{
editor.EditPage(pdfStamper, i);
}
}
将从即时页面内容流中删除所有文字绘图指令,例如对于我使用的示例PDF
它创建以下输出:
当心,如上所述,只有即时页面内容流会更改。对于完整的解决方案,必须将TextRemover
也应用到页面的XObjects和Patterns,并以递归方式应用。