PDFBox转Tiff内存溢出,如何压缩PDF中的JPEG图片?
解决JPEG添加到PDF后转Tiff内存溢出问题
你遇到的问题很典型——大尺寸JPEG直接加入PDF后,转Tiff时会因为内存占用过高抛出OutOfMemory异常。我们可以从图片预处理压缩和Tiff转换参数优化两个方向来解决,下面是具体的实现方案:
方案一:添加图片到PDF前压缩JPEG
在将JPEG转为PDImageXObject之前,先对图片进行压缩(调整尺寸或降低质量),这样能从源头减少内存占用。这里推荐两种实现方式:
用Thumbnails库压缩(简单易用)
首先确保引入依赖(Maven示例):
<dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.19</version> </dependency>
修改你的图片添加代码:
import net.coobird.thumbnailator.Thumbnails; import java.io.ByteArrayOutputStream; // 先压缩图片:可按需调整尺寸和质量 ByteArrayOutputStream baos = new ByteArrayOutputStream(); Thumbnails.of(imagePath) .size(1920, 1080) // 设置目标分辨率,比如1080P .outputQuality(0.7) // 图片质量(0.0-1.0,数值越低压缩率越高) .outputFormat("jpeg") .toOutputStream(baos); // 用压缩后的字节流创建PDImageXObject PDImageXObject image = PDImageXObject.createFromByteArray(doc, baos.toByteArray(), "compressed-image"); PDPage page = new PDPage(new PDRectangle(image.getWidth(), image.getHeight())); doc.addPage(page); try (PDPageContentStream contents = new PDPageContentStream(doc, page)) { contents.drawImage(image, 0, 0); } // try-with-resources会自动关闭流,无需手动调用close()
用JDK自带ImageIO压缩(无需额外依赖)
import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import javax.imageio.IIOImage; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import java.util.Iterator; // 读取原图片 BufferedImage originalImage = ImageIO.read(new File(imagePath)); // 配置JPEG压缩参数 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpeg"); ImageWriter writer = writers.next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(0.7f); // 设置压缩质量 // 将压缩后的图片写入字节流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); writer.setOutput(ImageIO.createImageOutputStream(baos)); writer.write(null, new IIOImage(originalImage, null, null), param); writer.dispose(); // 创建PDImageXObject并添加到PDF PDImageXObject image = PDImageXObject.createFromByteArray(doc, baos.toByteArray(), "compressed-image"); PDPage page = new PDPage(new PDRectangle(image.getWidth(), image.getHeight())); doc.addPage(page); try (PDPageContentStream contents = new PDPageContentStream(doc, page)) { contents.drawImage(image, 0, 0); }
方案二:优化PDF转Tiff的渲染参数
如果不想修改原图片,也可以在转Tiff时降低渲染分辨率、缩小图片尺寸,减少BufferedImage的内存占用:
修改你的PDF转Tiff代码:
document = PDDocument.load(new File(pdfFilename)); PDFRenderer pdfRenderer = new PDFRenderer(document); BufferedImage[] images = new BufferedImage[document.getNumberOfPages()]; for (int i = 0; i < document.getNumberOfPages(); i++) { // 两种优化方式选其一: // 方式1:降低渲染DPI(默认通常是300,设为96能大幅减少内存) images[i] = pdfRenderer.renderImageWithDPI(i, 96, ImageType.RGB); // 方式2:设置缩放比例(比如缩到原尺寸的50%) // images[i] = pdfRenderer.renderImage(i, 0.5f); } // 后续将BufferedImage写入Tiff的代码...
你可以根据实际需求选择方案:如果需要保留图片清晰度,优先调整转Tiff的渲染参数;如果PDF本身也需要更小的体积,推荐先压缩图片再添加到PDF。
内容的提问来源于stack exchange,提问作者Divya Neelaiah
相关产品推荐
相关产品推荐

