原创

PDFBox で PDF にデジタル署名するときに画像とテキストの順序を変更する

温馨提示:
本文最后更新于 2024年04月12日,已超过 37 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

PDFBox 3.0.1 ライブラリを使用して PDF ドキュメントに表現しています。 GitHub で提供されている例に基づいて、ドキュメントに表現するコードをなんとか書くことができましたが、視覚的な表現を作成します順序は、最初に提供するテキスト、次に画像であることに気付きました。 最初に画像を取得し、次に指定テキストを取得できるように、これら 2 つを交換しようとしましたが、提供した確信のサイズに応じて、小さいサイズでは機能しますが、大きいサイズでは画像とテキストが先に隠れてしまいます。

createVisualSignatureTempleteこれは、最初に画像を取得し、次にテキストを取得できるように変更しようとしたメソッドです。このクラスは、宣言の位置と幅、高さ、宣言テキストSignOptions指定するユーティリティクラスです。xy

private InputStream createVisualSignatureTemplate(
        PDDocument srcDoc,
        int pageNum,
        PDRectangle rect,
        PDSignature signature,
        SignOptions options
) throws IOException {
    try (PDDocument doc = new PDDocument()) {
        PDPage page = new PDPage(srcDoc.getPage(pageNum).getMediaBox());
        doc.addPage(page);
        PDAcroForm acroForm = new PDAcroForm(doc);
        doc.getDocumentCatalog().setAcroForm(acroForm);
        PDSignatureField signatureField = new PDSignatureField(acroForm);
        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        List<PDField> acroFormFields = acroForm.getFields();
        acroForm.setSignaturesExist(true);
        acroForm.setAppendOnly(true);
        acroForm.getCOSObject().setDirect(true);
        acroFormFields.add(signatureField);

        widget.setRectangle(rect);

        PDStream stream = new PDStream(doc);
        PDFormXObject form = new PDFormXObject(stream);
        PDResources res = new PDResources();
        form.setResources(res);
        form.setFormType(1);
        PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
        float height = bbox.getHeight();
        form.setBBox(bbox);
        PDFont font = PDType0Font.load(doc, new FileInputStream(fontPath));

        PDAppearanceDictionary appearance = new PDAppearanceDictionary();
        appearance.getCOSObject().setDirect(true);
        PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
        appearance.setNormalAppearance(appearanceStream);
        widget.setAppearance(appearance);

        try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) {
            float imgHeight = height / 2;
            float textHeight = height - imgHeight;

            if (options.getSignature_image() != null) {
                cs.saveGraphicsState();

                cs.transform(Matrix.getScaleInstance(0.25f, 0.25f));
                PDImageXObject img = PDImageXObject.createFromByteArray(doc, IOUtils.toByteArray(options.getSignature_image()), "image");
                cs.drawImage(img, 0, height);

                cs.restoreGraphicsState();
            }

            float fontSize = 8;
            float leading = fontSize * 1.2f;
            if (options.getSignature_text() != null) {
                String[] wrT = null;
                String s = null;
                wrT = WordUtils.wrap(options.getSignature_text(), 40).split("\\r?\\n");

                for (int i = 0; i < wrT.length; i++) {
                    cs.beginText();
                    cs.setFont(font, fontSize);
                    cs.setNonStrokingColor(Color.black);
                    cs.newLineAtOffset(fontSize, textHeight - (i + 1) * leading);
                    s = wrT[i];
                    cs.showText(s);
                    cs.endText();
                }
            }
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        doc.save(baos);
        return new ByteArrayInputStream(baos.toByteArray());
    }
}

コード行によって画像が小さく収まるように拡大縮小されることは承知しておりますcs.transform(Matrix.getScaleInstance(0.25f, 0.25f))が、イメージ画像を描画するのが困難になります。ここで、次のようにY位置を指定すると、cs.drawImage(img, 0, height)画像は左上隅からではなく、四角の中央のどこかに載せましょう。最初に画像、次にテキストを使用して視覚的なイメージを取得するもっと簡単な方法があれば、それを見せてくれてとても感謝します。

Rectangle2D humanRect = new Rectangle2D.Float(options.getSignature_posx(), options.getSignature_posy(), options.getSignature_width(), options.getSignature_height());

この例の場合:

posx = 440
posy = 577
width = 152
height = 62 (kinda works) / height = 162 (the image covers the text)

あえて使用する画像のサイズは 504x176 です

正文到此结束
热门推荐
本文目录