背景:
我有两张图像旋转 90 度(逆时针)并转换为 PDF。我使用了两种不同的工具来转换图像:
从视觉上看,使用 PDF 客户端时文档看起来完全相同。
问题:
我需要找到图像相对于PDF页面的位置信息。我的代码正确识别了一个文档的位置,但对另一个文档的定位是错误的:
可视化矩形信息,您可以看到文档 A(红色)没有旋转并且在 x 轴上超出太多:
详情:
使用PDFBox调试器,我可以看到文档A的图像通过CM操作旋转:
q
Q
q
/Perceptual ri
q
0 614.4 -792 0 792 0 cm
/Im1 Do
Q
Q
看来我没有正确考虑轮换。
代码:
Matrix matrix = getGraphicsState().getCurrentTransformationMatrix();
Rectangle2D.Double rectangle = new Rectangle2D.Double(
matrix.getTranslateX(),
matrix.getTranslateY(),
matrix.getScalingFactorX(),
matrix.getScalingFactorY()
);
尝试的解决方案
现在我可以从矩阵中获取旋转度数了:
protected int getRotation() {
Matrix matrix = getGraphicsState().getCurrentTransformationMatrix();
double rotationRadians = -Math.atan2(matrix.getShearY(), matrix.getScaleY());
return (int) Math.toDegrees(rotationRadians);
}
然后旋转矩形:
public Rectangle2D.Double rotate(Rectangle2D rectangle, int rotationDegrees) {
double x = rectangle.getX() + rectangle.getWidth();
double y = rectangle.getY();
AffineTransform rotationTransform = new AffineTransform();
rotationTransform.rotate(Math.toRadians(rotationDegrees), x, y);
Shape rotatedRectangle = rotationTransform.createTransformedShape(rectangle);
Rectangle2D bounds = rotatedRectangle.getBounds2D();
return (Rectangle2D.Double) bounds;
}
现在它的方向正确(绿色矩形),但需要滑过去:
我可以通过减去原始宽度和旋转宽度的总和来调整新矩形的 x 位置。感觉也许我可能会开始进入脆弱的领域。我也觉得我可能开始重新发明轮子了。
有没有更好的方法来解决这个问题?
更新:
经过进一步测试,该方案还需要对其他角度进行调整。我已经处理过 90、180、270。值得庆幸的是,我们通常不会遇到奇怪的角度,但当我们遇到奇怪的角度时,我有点担心。
在评论中您提到4个角的坐标将是您所需要的一切。
您可以通过遍历页面内容流指令来提取 PDF 中使用的位图图像的默认用户空间坐标,并在找到位图图像绘制指令时,将当时的“当前变换矩阵”应用到单位正方形的角上, (0, 0)、(0, 1)、(1, 0) 和 (1, 1)。 您可以使用专门的
PDFStreamEngine
来实现,如下所示:
public class UserSpaceCoordinatesPrinter extends PrintImageLocations {
public UserSpaceCoordinatesPrinter() throws IOException {
super();
}
@Override
protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
String operation = operator.getName();
if (OperatorName.DRAW_OBJECT.equals(operation)) {
COSName objectName = (COSName) operands.get(0);
PDXObject xobject = getResources().getXObject(objectName);
if (xobject instanceof PDImageXObject) {
System.out.println("\nFound image [" + objectName.getName() + "]");
Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
System.out.print("Corner coordinates in user space:");
for (Vector corner : UNIT_SQUARE_CORNERS) {
System.out.print(" " + ctm.transform(corner));
}
System.out.println();
} else if(xobject instanceof PDFormXObject) {
PDFormXObject form = (PDFormXObject)xobject;
showForm(form);
}
} else {
super.processOperator(operator, operands);
}
}
public static void print(PDDocument document) throws IOException {
UserSpaceCoordinatesPrinter printer = new UserSpaceCoordinatesPrinter();
int pageNum = 0;
for (PDPage page : document.getPages()) {
pageNum++;
System.out.println("\n\nProcessing page: " + pageNum);
System.out.println("Media box: " + page.getMediaBox());
System.out.println("Page rotation: " + page.getRotation());
printer.processPage(page);
}
}
final static List<Vector> UNIT_SQUARE_CORNERS = List.of(
new Vector(0, 0), new Vector(0, 1), new Vector(1, 0), new Vector(1, 1));
}
(PrintImageCornerCooperatives实用程序类) 你可以这样使用它:
try (PDDocument document = Loader.loadPDF(PDF_SOURCE)) {
UserSpaceCoordinatesPrinter.print(document);
}
打印图像角坐标测试testUserCoordinatesInput
)