从Itext PDF字节数组转换为多页TIFF文件

4

我有一个PDF文件(从iText生成的byte[]获得),需要发送到签名硬件。

由于与Java打印机驱动程序存在某些不兼容性,我无法直接发送PDF文件,因此需要在发送之前将其转换为图像。我已经成功将每个PDF页面转换为JPG文件,但客户不喜欢这种解决方案,因为签名不是在整个文档中,而只在单个页面中。

由于我没有找到任何免费的库,因此我决定分四步进行:

步骤1:使用iText生成PDF并将其持久化。

FileOutputStream fos = new FileOutputStream("tempFile.pdf");
fos.write(myByteArray);
fos.close();
fos.flush();

第二步:将多页PDF转换为List<java.awt.Image>

List<Image> images = null;

Ghostscript.getInstance(); // create gs instance

PDFDocument lDocument = new PDFDocument();
lDocument.load(new File("tempFile.pdf"));

SimpleRenderer renderer = new SimpleRenderer();

renderer.setResolution(300);

try 
{
    images = renderer.render(lDocument);
} 
catch (RendererException | DocumentException e) 
{
    e.printStackTrace();
}

步骤3:现在我遍历List<java.awt.Image>,将其转换为单个TIFF文件。

    int filename = 1;

    TIFFEncodeParam params = new TIFFEncodeParam();

    Iterator<Image> imageIterator = images.iterator();

    while (imageIterator.hasNext()) {
        BufferedImage  image = (BufferedImage) imageIterator.next();

        FileOutputStream os = new FileOutputStream(/*outputDir + */ filename + ".tif");

        JAI.create("encode", image , os, "TIFF", params);

        filename ++;
    }

步骤 4: 从多个单独的 TIFF 文件中创建多页 TIFF

BufferedImage image[] = new BufferedImage[paginas];
    for (int i = 0; i < paginas; i++) {
        SeekableStream ss = new FileSeekableStream((i + 1) + ".tif");
        ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);
        PlanarImage pi = new NullOpImage(decoder.decodeAsRenderedImage(0),null,null,OpImage.OP_IO_BOUND);
        image[i] = pi.getAsBufferedImage();
        ss.close();
    }

    TIFFEncodeParam params = new TIFFEncodeParam();
    params.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
    OutputStream out = new FileOutputStream(nombre +".tif");
    ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
    List <BufferedImage>list = new ArrayList<BufferedImage>(image.length);

    for (int i = 1; i < image.length; i++) {
        list.add(image[i]);
    }

    params.setExtraImages(list.iterator());
    encoder.encode(image[0]);
    out.close();

    System.out.println("Done.");

已完成。希望对其他遇到相同问题的人有所帮助。


将PDF文件签名后再进行转换打印不是更合理吗? - mkl
你从哪一行开始出现异常?是在ImageIO.read这一行吗?看起来你使用PDFBox导出的JPEG文件可能不存在或无法读取。这个问题是在循环中的第一个文件出现,还是在之后的某个(随机的?)时刻出现的?如果是后者,请尝试附上一个无法读取的样本文件。 :-) - Harald K
@mkl 设备被 Java / 系统视为打印机。 - Jordi Castilla
1
@JordiCastilla 设备被 Java / 系统视为打印机 - 嗯,感觉这是一个听起来很不错的设计,但最终证明它更像是一种负担而不是好处。叹气,抱歉。 - mkl
在这里,您可以找到一种更简单的方法,直接将PDF转换为多页TIFF,无需中间人。 - dragon66
显示剩余2条评论
1个回答

5
我不久前也遇到了同样的问题。我从这里得到了很多帮助: 多页tif 同时,还要检查一下: JAI (Java高级图像) 这里是将pdf页面转换为png图像的代码片段(使用org.apache.pdfbox库):
    PDDocument document = null;
    document = PDDocument.load(pdf1);

    int pageNum = document.getNumberOfPages();

    PDFImageWriter writer = new PDFImageWriter();
    String filename = pdf1.getPath() + "-";
    filename = filename.replace(".pdf", "");
    writer.writeImage(document, "png", "", 1, Integer.MAX_VALUE, filename);

    document.close();

然后,我将每个PNG图像转换为TIFF,再将多个TIFF图像合并成单个多页TIFF。


我使用itext将pdf页面转换为png,再从png转换为tiff。请查看更新的答案。 - Kiki
1
我使用JAI(Sun提供的免费库)将png转换为tiff。以下是一个示例:https://blog.idrsolutions.com/2009/06/saving-java-images-as-tifs-wth-jai/ - Kiki
很高兴能帮忙 :) 如果有帮到您,请不要忘记接受答案 :D - Kiki
接受了,你的回答足够有帮助... :D - Jordi Castilla
请查看此处的最新代码:https://dev59.com/a2Ag5IYBdhLWcg3wq8eU - Pipo
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接