使用iText替换BIRT生成的报告中的单个图像

时间:2018-01-10 12:31:24

标签: itext birt

我使用BIRT生成一个包含PDF输出的简单报告。这个文档有一些空白(填充了一个具有特定颜色的占位符图像,作为BIRT中的嵌入图像插入),我想用用户提供的图像替换它。

BIRT使用了iText,所以我决定使用iText,版本5.文档看起来像这样:

enter image description here

现在,我已编写此代码以填充仅第一个差距

private void replaceStream(PRStream orig, PdfStream stream) throws IOException {
    orig.clear();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    stream.writeContent(baos);
    orig.setData(baos.toByteArray(), false);
    for (PdfName name : stream.getKeys()) {
        orig.put(name, stream.get(name));
    }
}

private void placeSignature(File source, File target, File signature)
        throws IOException, DocumentException {
    PdfReader reader = new PdfReader(source.getPath());
    PdfObject obj;
    for (int i = 1; i <= reader.getXrefSize(); i++) {
        obj = reader.getPdfObject(i);
        if (obj != null && obj.isStream()) {
            PRStream stream = (PRStream) obj;

            byte[] b;
            try {
                b = PdfReader.getStreamBytes(stream);
            } catch (UnsupportedPdfException e) {
                b = PdfReader.getStreamBytesRaw(stream);
            }
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(b));

            if (img != null) {
                boolean signaturePlaceholder = true;
                for (int x = 0; x < img.getWidth(); x++) {
                    for (int y = 0; y < img.getHeight(); y++) {
                        // Check if image is a placeholder, matches a colour
                        if (img.getRGB(x, y) != -65) {
                            signaturePlaceholder = false;
                        }
                    }
                }
                if (signaturePlaceholder) {
                    Image img2 = Image.getInstance(signature.getPath());
                    PdfImage newImg = new PdfImage(img2, "", null);
                    replaceStream(stream, newImg);
                    System.out.println("Replaced!");
                    break;
                }
            }
        }
    }
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(target));
    stamper.close();
    reader.close();
}

@Test
public void testReplace() throws IOException, DocumentException {
    placeSignature(new File("src/test/resources/signature_test2.pdf"),
            new File("target/signature_test2.pdf"),
            new File("src/test/resources/signature.jpg"));
}

然而,在运行测试时,我得到的结果是:

enter image description here

似乎PDF流在所有图像标签中共享。但是,我想只更改第一个内容。如果我使用另一个图像来填充任何间隙(例如,不同的尺寸),它就不会被替换。

问题是,解析PDF时是否存在解决此问题的方法,或者在BIRT中创建报告时是否需要为每个占位符使用不同的图像。

这是示例PDF文件的the link

1 个答案:

答案 0 :(得分:2)

PDF中的页面仅包含单个图像XObject资源,该资源在单个表单XObject资源中使用,该资源在页面内容流中使用了三次。

因此,在您替换了唯一的图像资源后,页面上的所有(间接)用法都会显示替换图像。

如果您想使用iText更改此内容,则必须编辑内容流并使用新图像替换XObject使用表单的指令。但是,您首先必须确定哪些XObject用法是您要替换的那个。

非常重要,特别是如果Birt模板有些灵活的话。

我建议您在报告模板中的不同位置使用不同的图像(使用不同的标记颜色)。当然,当存在这样的占位符图像时,这当然变得越来越困难,特别是如果该数字是动态的并且可以变得任意大,例如,数据集中每个数据集条目一个,具有未知但可能有大量条目。