PDFBox 2.0:旋转页面上的不可见线条 - 剪辑路径问题
PDFBox 2.0: invisible lines on rotated page - clip path issue
文件示例:click here
使用 主题中的出色解决方案,我尝试提取可见文本。附加文档的文本非常小,这可能会导致某些字母部分可能被隐藏的剪辑路径问题。对于这样的旋转文本,我稍微更改了链接问题中的代码:
@Override
protected void processTextPosition(TextPosition text) {
PDGraphicsState gs = getGraphicsState();
Vector center = getTextPositionCenterPoint(text);
Area area = gs.getCurrentClippingPath();
if (area == null || area.contains(lowerLeftX + center.getX(), lowerLeftY + center.getY())) {
nonStrokingColors.put(text, gs.getNonStrokingColor());
renderingModes.put(text, gs.getTextState().getRenderingMode());
super.processTextPosition(text);
}
}
private Vector getTextPositionCenterPoint(TextPosition text) {
Matrix textMatrix = text.getTextMatrix();
Vector start = textMatrix.transform(new Vector(0, 0));
Vector center = null;
switch (rotation) {
case 0:
center = new Vector(start.getX() + text.getWidth()/2, start.getY());
break;
case 90:
center = new Vector(start.getX(), start.getY() + text.getWidth()/2);
break;
case 180:
center = new Vector(start.getX() - text.getWidth()/2, start.getY());
break;
case 270:
center = new Vector(start.getX(), start.getY() - text.getWidth()/2);
break;
default:
center = new Vector(start.getX() + text.getWidth()/2, start.getY());
break;
}
return center;
}
我正在尝试做的事情 - 根据旋转获取角色 X 中心点(我知道有时这不起作用,因为文本方向,但这里看起来并非如此)
但是在应用这个解决方案之后,由于剪辑路径,我在底部跳过了第二行、第三行和其他一些行。
我想知道我的错误在哪里。
提前致谢!
您的 PDF 问题是由
- 文本坐标正好在剪辑路径边界上;
- 文本坐标和剪辑路径坐标的计算路径不同,浮点误差不同,导致剪辑路径边界上的文本坐标有时被计算为剪辑路径外。
不幸的是,您尝试更改此设置在这里无济于事:问题文本的基线与剪辑路径边界重合,而您的 getTextPositionCenterPoint
仅沿基线居中,因此居中点的问题恰好是字形来源有问题。
另一种解决方法效果更好:使用脂肪点比较。这意味着我们不是检查给定点 x、y 是否在剪辑区域中,而是检查这些坐标周围的小矩形是否与剪辑区。如果坐标因浮点错误而偏离裁剪区域,这足以在裁剪区域中找到它们。
为此,我们将 processTextPosition
中的 area.contains(x, y)
检查替换为 contains(area, x, y)
,实现为
protected boolean contains(Area area, float x, float y) {
double length = .0002;
double up = 1.0001;
double down = .9999;
return area.intersects(x < 0 ? x*up : x*down, y < 0 ? y*up : y*down, Math.abs(x*length), Math.abs(y*length));
}
(PDFVisibleTextStripper辅助方法)
(其实这里选择坐标周围的矩形有点随意,这个选择对我来说很管用。)
通过此更改,我得到了底部缺少的 第 2、第 3 行和其他一些行,请参见。测试 ExtractVisibleText.testFat1.
文件示例:click here
使用
@Override
protected void processTextPosition(TextPosition text) {
PDGraphicsState gs = getGraphicsState();
Vector center = getTextPositionCenterPoint(text);
Area area = gs.getCurrentClippingPath();
if (area == null || area.contains(lowerLeftX + center.getX(), lowerLeftY + center.getY())) {
nonStrokingColors.put(text, gs.getNonStrokingColor());
renderingModes.put(text, gs.getTextState().getRenderingMode());
super.processTextPosition(text);
}
}
private Vector getTextPositionCenterPoint(TextPosition text) {
Matrix textMatrix = text.getTextMatrix();
Vector start = textMatrix.transform(new Vector(0, 0));
Vector center = null;
switch (rotation) {
case 0:
center = new Vector(start.getX() + text.getWidth()/2, start.getY());
break;
case 90:
center = new Vector(start.getX(), start.getY() + text.getWidth()/2);
break;
case 180:
center = new Vector(start.getX() - text.getWidth()/2, start.getY());
break;
case 270:
center = new Vector(start.getX(), start.getY() - text.getWidth()/2);
break;
default:
center = new Vector(start.getX() + text.getWidth()/2, start.getY());
break;
}
return center;
}
我正在尝试做的事情 - 根据旋转获取角色 X 中心点(我知道有时这不起作用,因为文本方向,但这里看起来并非如此) 但是在应用这个解决方案之后,由于剪辑路径,我在底部跳过了第二行、第三行和其他一些行。 我想知道我的错误在哪里。 提前致谢!
您的 PDF 问题是由
- 文本坐标正好在剪辑路径边界上;
- 文本坐标和剪辑路径坐标的计算路径不同,浮点误差不同,导致剪辑路径边界上的文本坐标有时被计算为剪辑路径外。
不幸的是,您尝试更改此设置在这里无济于事:问题文本的基线与剪辑路径边界重合,而您的 getTextPositionCenterPoint
仅沿基线居中,因此居中点的问题恰好是字形来源有问题。
另一种解决方法效果更好:使用脂肪点比较。这意味着我们不是检查给定点 x、y 是否在剪辑区域中,而是检查这些坐标周围的小矩形是否与剪辑区。如果坐标因浮点错误而偏离裁剪区域,这足以在裁剪区域中找到它们。
为此,我们将 processTextPosition
中的 area.contains(x, y)
检查替换为 contains(area, x, y)
,实现为
protected boolean contains(Area area, float x, float y) {
double length = .0002;
double up = 1.0001;
double down = .9999;
return area.intersects(x < 0 ? x*up : x*down, y < 0 ? y*up : y*down, Math.abs(x*length), Math.abs(y*length));
}
(PDFVisibleTextStripper辅助方法)
(其实这里选择坐标周围的矩形有点随意,这个选择对我来说很管用。)
通过此更改,我得到了底部缺少的 第 2、第 3 行和其他一些行,请参见。测试 ExtractVisibleText.testFat1.