iTextSharp:分割页面大小等于文件大小
本文关键字:小等 文件大小 分割 iTextSharp | 更新日期: 2023-09-27 18:05:10
我是这样分割一个大PDF (144mb)的:
public int SplitAndSave(string inputPath, string outputPath)
{
FileInfo file = new FileInfo(inputPath);
string name = file.Name.Substring(0, file.Name.LastIndexOf("."));
using (PdfReader reader = new PdfReader(inputPath))
{
for (int pagenumber = 1; pagenumber <= reader.NumberOfPages; pagenumber++)
{
string filename = pagenumber.ToString() + ".pdf";
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileStream(outputPath + "''" + filename, FileMode.Create));
document.Open();
copy.AddPage(copy.GetImportedPage(reader, pagenumber));
document.Close();
}
return reader.NumberOfPages;
}
}
对于大多数pdf(小尺寸,我猜是旧格式),一切都很好。但是对于一个更大的PDF(可能是使用refstreams之类的东西来更好地压缩),拆分页面作为一个页面打开,但其大小等于原始PDF的大小。我能做什么?
在您的文档top_gear_magazine_2012__09 . PDF的情况下,原因确实是我提到的:所有页面都引用对象 2.0 R作为它们的/资源,并且 2.0 obj中的字典依次引用PDF中的所有图像。
要将该文档拆分为只包含所需图像的部分文档,您应该对文档进行预处理,首先找出哪些图像属于哪些页面,然后为所有页面创建单独的/Resources字典。
由于您已经在此上下文中使用了iText,因此您还可以使用它来查找哪些页面需要哪些图像。使用iText parser
包使用RenderListener
实现逐页解析PDF,其RenderImage
方法只是记住当前页面上使用的图像对象。(作为一个特殊的转折,iText隐藏了所讨论的图像XObject的名称;但是,您可以获得间接对象,并且可以查询它的对象和生成号,这足以用于下一步。
在第二步中,在PdfStamper
中打开文档并遍历页面。对于每个页面,检索/Resources字典并复制它,但是只复制那些引用图像对象的XObjects引用,这些图像对象的对象编号和生成是在第一步中记住的。最后,将缩减后的副本设置为所讨论页面的/Resources字典。
生成的PDF应该拆分得很好。
PS最近在ittext邮件列表中出现了一个非常类似的问题。在该线程中,这里给出的解决方案配方得到了改进,以绕过iText隐藏xobject名称造成的困难,我现在建议在名称丢失之前进行干预,使用不同的ContentOperator
for"Do",这里是Java版本:
class Do implements ContentOperator
{
public void invoke(PdfContentStreamProcessor processor, PdfLiteral operator, ArrayList<PdfObject> operands) throws IOException
{
PdfName xobjectName = (PdfName)operands.get(0);
names.add(xobjectName);
}
final List<PdfName> names = new ArrayList<PdfName>();
}
这个内容操作符简单地收集所使用的xobject的名称,即为给定页面保留的xobject资源。