【问题标题】:Can PDFsharp help me detect overlapping text?PDFsharp 可以帮我检测重叠的文本吗?
【发布时间】:2016-06-01 14:34:30
【问题描述】:

问题:给定一个 PDF 文件,我是否可以(轻松)使用 PDFsharp(或其他 .NET 兼容的 PDF 库)检查重叠文本?

首选检查重叠字母(两个不同文本块)的解决方案,但也可以接受仅检查重叠边界框的解决方案。

我已经尝试过的方法:一个明显的解决方案是提取所有文本组件及其边界框并检查它们是否重叠。但是,我没有在 PDFsharp 中找到一种方法来提取带有边界框的文本组件。致avoid the XY problem,我问的是一般问题,而不是如何使用 PDFsharp 提取文本。


背景:我正在为我们的报告组件编写单元测试。报告生成为 PDF 文件,使用 RDLC 报告的 PDF 呈现组件以及使用 PdfSharp 直接输出 PDF。

在我的单元测试中,我想使用不同的数据集和语言来测试这些报告,并找出是否有重叠的文本。目前,单元测试只是为我想要测试的每个组合导出 PDF,并且必须有人手动查看它们。我想自动化它。

【问题讨论】:

    标签: c# unit-testing pdf pdfsharp


    【解决方案1】:

    下面的代码展示了如何使用XFINIUM.PDF 库实现这种检测(因为您询问了包括其他库在内的解决方案):

    public void TestCharacterOverlap()
    {
        PdfFixedDocument document = new PdfFixedDocument("sample.pdf");
    
        for (int i = 0; i < document.Pages.Count; i++)
        {
            List<PdfVisualRectangle[]> overlaps = GetPageOverlaps(document.Pages[i]);
            if (overlaps.Count > 0)
            {
                // We have character overlapping.
            }
        }
    }
    
    public List<PdfVisualRectangle[]> GetPageOverlaps(PdfPage page)
    {
        List<PdfVisualRectangle[]> overlaps = new List<PdfVisualRectangle[]>();
    
        PdfContentExtractor ce = new PdfContentExtractor(page);
        PdfTextFragmentCollection tfc = ce.ExtractTextFragments();
    
        for (int i = 0; i < tfc.Count; i++)
        {
            PdfTextGlyphCollection currentGlyphs = tfc[i].Glyphs;
    
            for (int j = 0; j < currentGlyphs.Count; j++)
            {
                // Start comparing current glyph to remaining extracted glyphs.
                for (int k = i; k < tfc.Count; k++)
                {
                    PdfTextGlyphCollection nextGlyphs = tfc[k].Glyphs;
                    // l = j + 1 - we avoid comparing current glyph with itself
                    for (int l = j + 1; l < nextGlyphs.Count; l++)
                    {
                        PdfVisualRectangle crtGlyphRect = GetGlyphRectangle(currentGlyphs[j].GlyphCorners);
                        PdfVisualRectangle nextGlyphRect = GetGlyphRectangle(nextGlyphs[l].GlyphCorners);
                        if (Intersect(crtGlyphRect, nextGlyphRect))
                        {
                            PdfVisualRectangle[] overlap = new PdfVisualRectangle[] { crtGlyphRect, nextGlyphRect };
                            overlaps.Add(overlap);
                        }
                    }
                }
            }
        }
    
        return overlaps;
    }
    
    public PdfVisualRectangle GetGlyphRectangle(PdfPoint[] glyphCorners)
    {
        double minX = Math.Min(Math.Min(glyphCorners[0].X, glyphCorners[1].X), Math.Min(glyphCorners[2].X, glyphCorners[3].X));
        double minY = Math.Min(Math.Min(glyphCorners[0].Y, glyphCorners[1].Y), Math.Min(glyphCorners[2].Y, glyphCorners[3].Y));
        double maxX = Math.Max(Math.Max(glyphCorners[0].X, glyphCorners[1].X), Math.Max(glyphCorners[2].X, glyphCorners[3].X));
        double maxY = Math.Max(Math.Max(glyphCorners[0].Y, glyphCorners[1].Y), Math.Max(glyphCorners[2].Y, glyphCorners[3].Y));
    
        return new PdfVisualRectangle(minX, minY, maxX - minX, maxY - minY);
    }
    
    public bool Intersect(PdfVisualRectangle rc1, PdfVisualRectangle rc2)
    {
        bool intersect = (rc1.Left < rc2.Left + rc2.Width) && (rc1.Left + rc1.Width > rc2.Left) &&
            (rc1.Top < rc2.Top + rc2.Height) && (rc1.Top + rc1.Height > rc2.Top);
    
        return intersect;
    }
    

    关于代码的几点说明:
    - 在大多数情况下(常规水平文本),字形角(4 个点)形成一个矩形。但是对于对角线文本或倾斜字符,字形角是四边形,因此您必须实现更复杂的交集过程
    - 重叠测试可以进一步完善,以允许小程度的重叠,如果交叉点大于字符区域的 X%,则假设 2 个字符重叠。这就是 GetPageOverlaps 方法返回成对矩形集合的原因,以便在需要时对其进行进一步处理。

    免责声明:我为开发 XFINIUM.PDF 库的公司工作。

    【讨论】:

    • 请注意,您可能必须制定一种策略来处理kerning 以避免误报。
    猜你喜欢
    • 2021-12-26
    • 2014-09-18
    • 1970-01-01
    • 2012-07-24
    • 2021-11-03
    • 2010-10-28
    • 1970-01-01
    • 2021-11-25
    • 2022-11-24
    相关资源
    最近更新 更多