我正在使用 iText7 和修改后的提取策略提取 PDF 中行和文本的位置。无论采用何种提取策略,线段和文本的位置似乎都不在同一比例上。
这是最简单的提取策略,覆盖 LocationTextExtractionStrategy,线段位置的比例约为文本位置的 2/3。关于我错过了什么/做错了什么有什么建议吗?:
class LocationStrategyTextAndLines : LocationTextExtractionStrategy
{
public List<TextChunk> textChunkResult = new List<TextChunk>();
public List<Line> lineResult = new List<Line>();
public override void EventOccurred(IEventData data, EventType type)
{
// get all line segments
if (type.Equals(EventType.RENDER_PATH))
{
PathRenderInfo pRenderInfo = (PathRenderInfo)data;
Path path = pRenderInfo.GetPath();
path.ReplaceCloseWithLine();
foreach (Subpath sPath in path.GetSubpaths())
{
List<IShape> segments = (List<IShape>)sPath.GetSegments();
AddLines(segments);
}
}
if (!type.Equals(EventType.RENDER_TEXT))
return;
// get text and text location info
TextRenderInfo renderInfo = (TextRenderInfo)data;
Debug.WriteLine(renderInfo.GetText());
string curFont = renderInfo.GetFont().GetFontProgram().ToString();
float curFontSize = renderInfo.GetFontSize();
TextChunk chunk = new TextChunk();
chunk.text = renderInfo.GetText();
Vector letterStart = renderInfo.GetBaseline().GetStartPoint();
Vector letterEnd = renderInfo.GetAscentLine().GetEndPoint();
float startX = Math.Min(letterStart.Get(0), letterEnd.Get(0));
float startY = Math.Min(letterStart.Get(1), letterEnd.Get(1));
Rectangle letterRect = new Rectangle(startX, startY, Math.Abs(letterEnd.Get(0) - letterStart.Get(0)), Math.Abs(letterEnd.Get(1) - letterStart.Get(1)));
chunk.rect = letterRect;
textChunkResult.Add(chunk);
}
private void AddLines(List<IShape> segments)
{
foreach (IShape segment in segments)
{
if (segment is Line) {
lineResult.Add((Line)segment);
}
}
}
}
public class TextChunk
{
public string text { get; set; }
public Rectangle rect { get; set; }
public TextChunk()
{
}
public TextChunk(string text, Rectangle rect)
{
this.text = text;
this.rect = rect;
}
}
我尝试了多种提取文本和线条的方法,但结果始终相同。如果有帮助的话,如果我在页面大小的画布上重新绘制数据,则文本块似乎位于正确的位置,但线段彼此之间的组织方式正确,但比例约为 2/3。
我发现了线段的 X 和 Y 缩放因子,我应用了它,它似乎工作正常。
pathRenderInfo.GetGraphicsState().GetCtm();