2

次のコードを使用して、iText ライブラリを使用して既存の pdf のすべてのページ(上部と下部) を縮小しています。

コードは正常に動作します。しかし、結果の pdfを処理すると、すべてのページの回転に対して0 の値が得られますが、古い pdf には他の回転 (つまり 90 度) もあります。

このまま回転をキープしたいのですが出来ません。

以下のようにページを縮小するために使用しているコード

public void shrinkPDFPages() throws Exception {
        PdfReader reader = new PdfReader("D:/testpdfs/test.pdf");

        Document doc = new Document();
        PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(
                "D://testpdfs/result.pdf"));
        doc.open();
        PdfContentByte cb = writer.getDirectContent();
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {

            PdfImportedPage page = writer.getImportedPage(reader, i);
            float pageHeight = reader.getPageSizeWithRotation(i).getHeight();
            float pageWidth = reader.getPageSizeWithRotation(i).getWidth();
            int rotation = reader.getPageRotation(i);

            Rectangle pageRectangle = reader.getPageSizeWithRotation(i);
            Rectangle PageRect = null;

            System.out.println(rotation);

            switch (rotation) {
            case 0:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                AffineTransform af = new AffineTransform();
                af.scale(1, 0.84f);
                af.translate(1, 50);

                cb.addTemplate(page, af);
                break;
            case 90:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();

                cb.addTemplate(page, 0, -1f, 0.84f, 0, 50, pageHeight);
                break;
            case 270:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                cb.addTemplate(page, 0, 1f, -0.84f, 0, pageWidth - 50, 0);
                break;

            case 180:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                cb.addTemplate(page, -1f, 0, 0, -0.84f, pageWidth,
                        pageHeight - 50);
                break;
            default:
                break;

            }
        }
        doc.close();
    }

私は何をすべきか?なので回転はそのまま。

私が取得しているもう1つの問題は、内部ハイパーリンクを保持できないことです。

実際の pdf ページ:

ここに画像の説明を入力

縮小後(コンテンツの縮小):

ここに画像の説明を入力

4

1 に答える 1

2

PDF をスケーリングしてページを大きくするのは簡単です。これは、ScaleRotateの例に示されています。ユーザーユニットのデフォルトバージョンを変更するだけです。デフォルトでは、この単位は 1 です。これは、1 ユーザー単位が 1 ポイントに等しいことを意味します。この値を 75,000 に増やすことができます。ユーザー単位の値が大きいほど、ページが大きくなります。

残念ながら、ユーザー単位は 1 より小さくなることはありません。そのため、この手法を使用してページを縮小することはできません。ページを縮小したい場合は、変換を導入する必要があります (結果として新しい CTM が生成されます)。

これはShrinkPdfの例に示されています。この例では、 8.26 x 11.69 インチの大きさのhero.pdfという名前の PDF を取り、それを 50% 縮小して、4.13 x 5.85 インチの大きさのhero_shrink.pdfという名前の PDF を作成します。

これを実現するには、汚いハックが必要です。

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    int n = reader.getNumberOfPages();
    PdfDictionary page;
    PdfArray crop;
    PdfArray media;
    for (int p = 1; p <= n; p++) {
        page = reader.getPageN(p);
        media = page.getAsArray(PdfName.CROPBOX);
        if (media == null) {
            media = page.getAsArray(PdfName.MEDIABOX);
        }
        crop = new PdfArray();
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(media.getAsNumber(2).floatValue() / 2));
        crop.add(new PdfNumber(media.getAsNumber(3).floatValue() / 2));
        page.put(PdfName.MEDIABOX, crop);
        page.put(PdfName.CROPBOX, crop);
        stamper.getUnderContent(p).setLiteral("\nq 0.5 0 0 0.5 0 0 cm\nq\n");
        stamper.getOverContent(p).setLiteral("\nQ\nQ\n");
    }
    stamper.close();
    reader.close();
}

すべてのページをループし、各ページのトリミング ボックスを取得します。クロップ ボックスがない場合は、メディア ボックスを使用します。これらのボックスは、4 つの数値の配列として格納されます。この例では、最初の 2 つの数値がゼロであると仮定し、次の 2 つの値を 2 で割り、ページを 50% に縮小します (最初の 2 つの値がゼロでない場合は、より複雑な数式が必要になります)。

新しい配列を入手したら、メディア ボックスとクロップ ボックスをこの配列に変更し、すべてのコンテンツを 50% に縮小する CTM を導入します。setLiteral()メソッドを使用してiTextをだます必要があります。

コメント セクションでのフィードバックによると、私の例で説明されているメカニズムを理解していないようです。したがって、ShrinkPdf2という名前の 2 番目の例を作成しました。

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    int n = reader.getNumberOfPages();
    float percentage = 0.8f;
    for (int p = 1; p <= n; p++) {
        float offsetX = (reader.getPageSize(p).getWidth() * (1 - percentage)) / 2;
        float offsetY = (reader.getPageSize(p).getHeight() * (1 - percentage)) / 2;
        stamper.getUnderContent(p).setLiteral(
                String.format("\nq %s 0 0 %s %s %s cm\nq\n", percentage, percentage, offsetX, offsetY));
        stamper.getOverContent(p).setLiteral("\nQ\nQ\n");
    }
    stamper.close();
    reader.close();
}

この例では、ページ サイズを変更せず (メディアやクロップ ボックスを変更しません)、コンテンツを縮小するだけ (この場合は 80% に) し、縮小したコンテンツをページの中央に配置して、より大きな余白を残します。上、下、左、右。

ご覧のとおり、これは正しい数学を適用するだけの問題です。この 2 番目の例は最初の例よりもさらに単純なので、さらに複雑にしました。パーセンテージを簡単に変更できるようになりました (最初の例では 50% をハードコードしました。この場合、percentage変数を導入し、それを 80% と定義しました) 。 .

縦横比を維持するために、Y 方向だけでなく X 方向にもスケーリングを適用していることに注意してください。スクリーン ショットを見ると、コンテンツを Y 方向にのみ縮小したいようです。たとえば、次のようにします。

String.format("\nq 1 0 0 %s 0 %s cm\nq\n", percentage, offsetY)

必要に応じてコードを自由に変更してください。ただし...結果は見苦しくなります。すべてのテキストが変に見え、垂直に立っている人の写真に適用すると太って見えます。

于 2014-09-08T08:49:47.927 に答える