pdfbox-转换为灰度后pdf大小增加

问题描述 投票:0回答:1

我需要将扫描的PDF转换为灰度PDF。我找到了两种解决方案。

第一个是只使用renderImage

private void convertToGray() throws IOException {
    File pdfFile = new File(PATH);
    try (PDDocument originalPdf = PDDocument.load(pdfFile);
         PDDocument doc = new PDDocument()) {
        LOGGER.info("Current heap after loading file: {}", Runtime.getRuntime().totalMemory());
        PDFRenderer pdfRenderer = new PDFRenderer(originalPdf);
        for (int pageNum = 0; pageNum < originalPdf.getNumberOfPages(); pageNum++) {
//          PDImageXObject pdImage = LosslessFactory.createFromImage(doc, bufferedImage);
            BufferedImage grayImage = pdfRenderer.renderImageWithDPI(pageNum, 300F, ImageType.GRAY);
            PDImageXObject pdImage = JPEGFactory.createFromImage(doc, grayImage);
            float pageWight = originalPdf.getPage(pageNum).getMediaBox().getWidth();
            float pageHeight = originalPdf.getPage(pageNum).getMediaBox().getHeight();
            PDPage page = new PDPage(new PDRectangle(pageWight, pageHeight));
            doc.addPage(page);
            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
                contentStream.drawImage(pdImage, 0F, 0F, pageWight, pageHeight);
            }
        }
        doc.save(NEW_PATH);
    }
}

但是这会导致文件大小增加(因为某些PDF的DPI少于300。

第二个是用灰色模拟物替换现有图像

private void convertByImageToGray() throws IOException {
    File pdfFile = new File(PATH);
    try (PDDocument document = PDDocument.load(pdfFile)) {
        List<COSObject> objects = document.getDocument().getObjectsByType(COSName.IMAGE);
        for (COSObject object : objects) {
            LOGGER.info("Class: {}; {}", object.getClass(), object.toString());
        }
        for (int pageNum = 0; pageNum < document.getNumberOfPages(); pageNum++) {
            PDPage page = document.getPage(pageNum);
            replaceImage(document, page);
        }
        document.save(NEW_PATH);
    }
}

private void replaceImage(PDDocument document, PDPage page) throws IOException {
    PDResources resources = page.getResources();
    Iterable<COSName> xObjectNames = resources.getXObjectNames();
    if (xObjectNames != null) {
        for (COSName xObjectName : xObjectNames) {
            PDXObject object = resources.getXObject(xObjectName);
            if (object instanceof PDImageXObject) {
                PDImageXObject img1 = (PDImageXObject) object;
                BufferedImage bufferedImage1 = img1.getImage();
                BufferedImage grayBufferedImage = convertBufferedImageToGray(bufferedImage1);
//                    PDImageXObject grayImage = JPEGFactory.createFromImage(document, grayBufferedImage);
                PDImageXObject grayImage = LosslessFactory.createFromImage(document, grayBufferedImage);
                resources.put(xObjectName, grayImage);
            }
        }
    }
}

private static BufferedImage convertBufferedImageToGray(BufferedImage sourceImg) {
    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ColorConvertOp op = new ColorConvertOp(sourceImg.getColorModel().getColorSpace(), cs, null);
    op.filter(sourceImg, sourceImg);
    return sourceImg;
}

但是仍然有些文件的大小增加了3倍(即使它们已经是灰度的;有趣的是,在这种情况下JPEGFactory会产生比LosslessFactory大的文件)。灰度PDF格式的所有图像均具有与原始图像相同的尺寸。而且我不明白为什么。

也许有更好的方法来制作具有可预测大小的灰度PDF(除了Ghostscript)?

UPDATE:我刚刚意识到问题在于从图像创建PDF。它也不会压缩。

例如,我的虚拟一页扫描文件小于1 Mb。但是,如果我从中获取图像(通过Acrobat Reader直接复制到Paint或通过上面的代码复制),则其大小约为8-10 Mb,具体取决于方法。而且,如果我从该图像创建新的PDF,则几乎不会压缩。这是示例代码:

File pdfFile = new File(FULL_FILE);
try (PDDocument document = PDDocument.load(pdfFile)) {
    PDPage page = new PDPage();
    document.addPage(page);
    PDImageXObject pdImage = PDImageXObject.createFromFile("example.png", document);
    try (PDPageContentStream contents = new PDPageContentStream(document, page)) {
        contents.drawImage(pdImage, 0F, 0F);
    }
    document.save(FULL_FILE_NEW);
}
java pdf pdfbox
1个回答
2
投票

是,与JPEGFactory相比,LosslesslessFactory产生的文件更小

在下面的链接中,有多种方法可以尝试实现相同的目标。总体而言,质量最好的灰度图像是选项6中的图像,但这绝不是最快的。还提供了比较供您选择

This链接包含将彩色图像转换为黑色的可能方法。这对我帮助很大。让我知道它是否对您有用,如果有帮助,请批准我的回答。

© www.soinside.com 2019 - 2024. All rights reserved.