如何调整文本或图片角度?PDFBox旋转水印出现偏移怎么解决
问题原因
你当前的旋转偏移是因为Matrix.getRotateInstance()的后两个参数设置为(0,0),代表围绕PDF页面默认的坐标原点(左下角)旋转,旋转后文本坐标系被整体偏转,自然会偏离预期位置。
解决方法
PDFBox的Matrix类本身就支持自定义旋转锚点生成旋转矩阵,不需要额外工具,只需要调整旋转锚点为你期望的水印旋转中心即可,步骤如下:
- 先计算水印文本的实际宽度,配合字体大小得到文本的实际占据尺寸
- 确定你期望的水印放置位置,以该位置下的水印自身中心/你指定的点作为旋转锚点
- 生成旋转矩阵时传入该锚点坐标即可
修改后可正常使用的代码如下:
public static void addTextWatermark(PDDocument doc, PDPage page, PDFont font, TextParam param) throws IOException { try (PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true)) { // 1. 获取页面尺寸,若页面有自定义裁剪区域可替换为getCropBox() PDRectangle pageRect = page.getMediaBox(); float pageWidth = pageRect.getWidth(); float pageHeight = pageRect.getHeight(); float fontSize = param.getFontSize(); // 2. 计算文本实际宽度 float textWidth = font.getStringWidth(param.getText()) / 1000 * fontSize; // 3. 定义水印放置的目标位置,示例为页面居中,可自行修改为其他坐标 float targetX = (pageWidth - textWidth) / 2; float targetY = (pageHeight - fontSize) / 2; // 4. 旋转锚点设为水印自身的中心,保证旋转时水印围绕自身中心转,不会偏移位置 float anchorX = targetX + textWidth / 2; float anchorY = targetY + fontSize / 2; // 替换原来的旋转代码,传入自定义锚点 cs.transform(Matrix.getRotateInstance(Math.toRadians(param.getDegree()), anchorX, anchorY)); cs.setFont(font, fontSize); PDExtendedGraphicsState gs = new PDExtendedGraphicsState(); gs.setNonStrokingAlphaConstant(param.getDissolve() / 100f); gs.setStrokingAlphaConstant(param.getDissolve() / 100f); gs.setBlendMode(BlendMode.MULTIPLY); gs.setLineWidth(3f); cs.setGraphicsStateParameters(gs); //设置字体和边框颜色 cs.setNonStrokingColor(new Color(param.getFills()[0], param.getFills()[1], param.getFills()[2])); cs.setStrokingColor(new Color(param.getFills()[0], param.getFills()[1], param.getFills()[2])); cs.beginText(); // 这里传入目标位置坐标即可 cs.newLineAtOffset(targetX, targetY); cs.showText(param.getText()); cs.endText(); } }
额外说明
如果需要放置图片水印,逻辑完全一致:先拿到图片的宽高,确定图片放置的目标坐标,再以图片中心为锚点生成旋转矩阵即可。
内容的提问来源于stack exchange,提问作者markjrzhang
相关产品推荐
相关产品推荐

