2

大きなPDF(144 mb)を分割する方法は次のとおりです。

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(小さいサイズで、古い形式だと思います)では、すべて正常に機能します。しかし、より大きなもの(おそらく、より良い圧縮のためにrefstreamsのようなものを使用している)の場合、分割されたページは1ページとして開きますが、そのサイズは元のPDFのサイズと同じです。私に何ができる?

4

1 に答える 1

7

ドキュメントTop_Gear_Magazine_2012_09.pdfの場合、その理由は確かに私が述べたものです。すべてのページがオブジェクト2 0Rを/Resourcesとして参照し、 20objの辞書がPDF内のすべての画像を参照します。

そのドキュメントを必要な画像のみを含む部分的なドキュメントに分割するには、最初にどの画像がどのページに属しているかを調べ、次にすべてのページに個別の/Resourcesディクショナリを作成してドキュメントを前処理する必要があります。

このコンテキストではすでにiTextを使用しているので、これを使用して、どのページにどの画像が必要かを調べることもできます。iTextパッケージを使用して、現在のページで使用されている画像オブジェクトをメソッドが単に記憶する実装をparser使用して、PDFをページごとに最初に解析します。(特別な工夫として、iTextは問題の画像XObjectの名前を非表示にします。ただし、間接オブジェクトを取得し、次のステップに十分なオブジェクトと世代番号を照会できます。)RenderListenerRenderImage

2番目のステップでは、でドキュメントを開き、PdfStamperページを繰り返し処理します。ページごとに/Resourcesディクショナリを取得してコピーしますが、最初のステップでそれぞれのページに対してオブジェクト番号と世代を覚えている画像オブジェクトの1つを参照するXObjects参照のみをコピーします。最後に、減少したコピーを問題のページの/Resourcesディクショナリとして設定します。

結果のPDFはうまく分割されるはずです。

PS最近、非常によく似た問題がiTextメーリングリストで発生しました。そのスレッドでは、ここで提供されるソリューションレシピが改善され、iTextがxobject名を非表示にすることによって引き起こされる問題を回避するために、名前が失われる前に、別ContentOperatorの「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リソースを収集するだけです。

于 2013-03-22T15:05:16.493 に答える