PDFBox结合Zxing识别条码时如何加载项目资源中的条码字体
解决方案
问题核心原因
你之前两种方案失效的根因:
- 手动向页面资源添加字体的方式完全不生效:PDF内条码元素已经绑定了固定的字体名称引用,你新增的字体和原引用的字体标识不匹配,PDFRenderer渲染时不会调用
- 向AWT GraphicsEnvironment注册字体失效大概率是时机不对/字体加载失败,且PDFBox自有字体查找优先级高于系统注册字体,默认不会优先调用你注册的字体
可行实现方案
方案1:向PDFBox注入自定义字体(优先推荐,兼容性最高)
PDFBox 2.x+版本支持自定义字体提供器,直接将你项目内的条码字体注入到渲染器的字体搜索路径即可,不需要修改原PDF内容:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.rendering.DefaultFontProvider; import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont; import java.awt.image.BufferedImage; import java.io.InputStream; // 1. 先从项目资源加载两款条码字体,构造自定义字体提供器 DefaultFontProvider customFontProvider = new DefaultFontProvider(true, true, true); // 加载第一款条码字体 try (InputStream font1Is = getClass().getResourceAsStream("/fonts/yourBarcodeFont1.ttf")) { PDTrueTypeFont font1 = PDTrueTypeFont.loadTTF(null, font1Is); customFontProvider.addFont(font1); } // 加载第二款条码字体 try (InputStream font2Is = getClass().getResourceAsStream("/fonts/yourBarcodeFont2.ttf")) { PDTrueTypeFont font2 = PDTrueTypeFont.loadTTF(null, font2Is); customFontProvider.addFont(font2); } // 2. 加载PDF文档、构造渲染器,绑定自定义字体提供器 try (PDDocument document = PDDocument.load(你的PDF字节数组)) { PDFRenderer renderer = new PDFRenderer(document); // 注入自定义字体提供器 renderer.setFontProvider(customFontProvider); // 渲染图片,条码识别建议用300DPI以上 BufferedImage image = renderer.renderImageWithDPI(0, 300); // 后续交给ZXing识别即可 }
方案2:AWT字体注册的正确姿势
如果要用GraphicsEnvironment注册,必须确保注册动作在PDFRenderer实例化之前完成,且确认字体加载无异常:
import java.awt.Font; import java.awt.GraphicsEnvironment; import java.io.InputStream; // 提前注册字体,必须在PDFRenderer初始化前执行 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); // 从资源加载字体 try (InputStream font1Is = getClass().getResourceAsStream("/fonts/yourBarcodeFont1.ttf")) { Font barcodeFont1 = Font.createFont(Font.TRUETYPE_FONT, font1Is); ge.registerFont(barcodeFont1); } try (InputStream font2Is = getClass().getResourceAsStream("/fonts/yourBarcodeFont2.ttf")) { Font barcodeFont2 = Font.createFont(Font.TRUETYPE_FONT, font2Is); ge.registerFont(barcodeFont2); } // 再执行PDF加载、渲染逻辑 try (PDDocument document = PDDocument.load(你的PDF字节数组)) { PDFRenderer renderer = new PDFRenderer(document); BufferedImage image = renderer.renderImageWithDPI(0, 300); }
注意事项
- 加载字体前可以先打印PDF内用到的字体名称,确保你加载的条码字体的PostScript名称和PDF内引用的字体名称完全一致,才能匹配成功:
document.getPage(0).getResources().getFonts().forEach((name, font) -> { System.out.println("字体引用名:" + name + ",实际字体名:" + font.getFontDescriptor().getFontName()); }); - 条码识别建议渲染DPI设置为300及以上,过低的分辨率会导致ZXing识别失败
- 不要手动修改PDF页面资源添加字体,该操作会修改原PDF结构,不会解决渲染匹配问题
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

