使用PDFBox将ZXing生成的条形码写入PDF耗时过长如何优化
优化方案
核心性能瓶颈
- 不必要的图像编解码开销:生成条形码时将
BitMatrix编码为PNG字节数组,绘制时又将PNG字节数组解码为BufferedImage,两次编解码操作完全冗余,是最大的性能开销来源。 - 图像压缩方式不合理:条形码属于二值单色图像,用默认的无损PNG存储效率极低,解码和嵌入PDF的耗时都会显著增加。
具体优化措施
1. 移除中间PNG编解码环节,直接从BitMatrix生成PDImageXObject
跳过PNG压缩、解压缩的冗余步骤,直接用条形码原始二值数据生成PDF支持的图像,配合针对二值图像优化的CCITT Group 4压缩,处理效率会提升数十倍。
示例代码如下:
// 改写条形码生成方法,直接返回BitMatrix,省略中间PNG生成步骤 private static BitMatrix generateBarCodeBitMatrix(String barcodeText, int width, int height, Writer writer, BarcodeFormat barcodeFormat) throws WriterException { if (Objects.isNull(barcodeText) || width <= 0 || height <= 0) { throw new IllegalArgumentException(String.format("generateBarCode: wrong input values %s %s %s %s", barcodeText, width, height, barcodeFormat.name())); } Map<EncodeHintType, Object> hintMap = new EnumMap<>(EncodeHintType.class); hintMap.put(EncodeHintType.MARGIN, 0); return writer.encode(barcodeText, barcodeFormat, width, height, hintMap); } // 直接从BitMatrix生成适配PDF的二值图像,使用CCITT G4压缩 public static PDImageXObject createBarcodeImageFromBitMatrix(PDDocument document, BitMatrix bitMatrix) throws IOException { int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); byte[] matrixData = new byte[(width + 7) / 8 * height]; for (int y = 0; y < height; y++) { bitMatrix.getRow(y, matrixData, y * ((width + 7) / 8)); } return CCITTFactory.createFromByteArray(document, width, height, 1, matrixData, CCITTConstants.COMPRESSION_CCITT_T6, 0, 0); } // 优化后的绘制方法,直接传入预生成的PDImageXObject public static void drawBarcode(PDPageContentStream contentStream, int x, int y, PDImageXObject barcodeImage, Integer width, Integer height) throws IOException { if (width != null && height != null) { contentStream.drawImage(barcodeImage, x, y, width, height); return; } contentStream.drawImage(barcodeImage, x, y); }
2. 复用可复用资源
如果存在重复内容的条形码,可将生成的PDImageXObject存入本地缓存,同一内容的条形码无需重复生成,进一步降低开销。
3. 批量生成额外优化
- 固定相同规格条形码的生成尺寸,避免动态计算开销
- 批量生成时复用字节缓冲区,避免频繁创建销毁IO对象
- 无需透明通道的场景不要使用带alpha的图像格式,降低处理开销
按照上述方案调整后,1000页带条形码的PDF生成耗时可降低到10秒以内,和PHP实现的性能基本持平。
内容的提问来源于stack exchange,提问作者Terry Sposato
相关产品推荐
相关产品推荐

