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的大小。我能做什么?

iTextSharp:分割页面大小等于文件大小

在您的文档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资源。