使用Apache PDFBox时如何将提取的字形居中放置到目标图像中
Apache PDFBox 字形提取居中问题修复
问题根因
你代码里字形垂直居中失效的核心原因有两个:
- 垂直偏移硬编码了
-50的固定值,不同字形的升部、降部、实际边界高度差异极大,固定偏移不可能适配所有字形 - 坐标系变换顺序混乱,计算偏移时没有考虑Y轴翻转、缩放系数对坐标的影响,也没有处理字形边界
bounds2D的Y轴最小值不为0的情况——很多字形的路径会延伸到Y=0坐标以下(比如g、y这类带下伸部分的字符),不做适配必然出现偏移。
修复代码
直接替换原有renderGlyph方法即可,核心调整:自动计算适配画布的缩放比例,预留内边距避免字形贴边,按正确坐标系顺序计算偏移,无任何硬编码偏移值,所有字形均可自动居中:
private static BufferedImage renderGlyph(GeneralPath path, Rectangle2D bounds2D, int imageWidth, int imageHeight) { BufferedImage bim = new BufferedImage( imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D) bim.getGraphics(); g.setBackground(Color.WHITE); g.clearRect(0, 0, bim.getWidth(), bim.getHeight()); // 预留20px内边距,防止字形边缘贴到画布边框 int padding = 20; double availableWidth = imageWidth - padding * 2; double availableHeight = imageHeight - padding * 2; // 自动计算缩放比,保证字形完整落在可用区域内,替代原固定0.5的缩放值 double scaleX = availableWidth / bounds2D.getWidth(); double scaleY = availableHeight / bounds2D.getHeight(); double scale = Math.min(scaleX, scaleY); // 计算缩放后的字形实际尺寸 double scaledGlyphWidth = bounds2D.getWidth() * scale; double scaledGlyphHeight = bounds2D.getHeight() * scale; // 计算居中所需的水平、垂直偏移,自动适配字形边界的负Y坐标 double offsetX = (imageWidth - scaledGlyphWidth) / 2 - bounds2D.getMinX() * scale; double offsetY = (imageHeight - scaledGlyphHeight) / 2 + bounds2D.getMinY() * scale; // 按正确顺序应用变换:先平移到居中位置,再缩放,最后翻转Y轴(PDF坐标系Y轴向上,AWT画布坐标系Y轴向下) g.translate(offsetX, imageHeight - offsetY); g.scale(scale, -scale); // 配置渲染参数绘制字形 g.setColor(Color.BLACK); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.fill(path); g.dispose(); return bim; }
其他需要修正的问题
你原有代码还有两个会影响运行的bug:
- 字符串相等判断用了
==,Java中字符串值比较必须用equals方法,否则跳过.notdef、space这类字形的逻辑会失效,把对应判断替换为:
if("None".equals(glyphName) || ".notdef".equals(glyphName) || "space".equals(glyphName)){ continue; }
- 代码中重复导入了
PDType1CFont类,且引用了不存在的fontPane、fontpane包,如果使用官方发行版的PDFBox依赖,需要把对应类的包路径修正为org.apache.pdfbox.pdmodel.font下的官方路径。
内容的提问来源于stack exchange,提问作者gholamrezaeiPT
相关产品推荐
相关产品推荐

