2016-06-01 1 views
0

Вопрос: Если у вас есть PDF-файл, могу ли я (легко) проверить перекрывающий текст с помощью PDFsharp (или другой совместимой с .NET библиотекой PDF)?Может ли PDFsharp помочь мне обнаружить перекрывающийся текст?

Решение, которое проверяет перекрывающиеся буквы (из двух разных текстовых блоков), является предпочтительным, но приемлемо решение, которое проверяет только перекрывающиеся ограничивающие поля.

Что я уже пробовал: Очевидным решением было бы извлечь все текстовые компоненты своими ограничительными рамками и проверить их для перекрытия. Однако в PDFsharp я не нашел способ извлечь текстовые компоненты с их ограничивающими прямоугольниками. К avoid the XY problem, я прошу об общей проблеме, а не о том, как извлечь текст с помощью PDFsharp.


фон: Я пишу тесты для нашего компонента отчетности. Отчеты генерируются как файлы PDF, используя как компонент рендеринга PDF отчетов RDLC, так и прямой PDF-выход с PdfSharp.

В моих модульных тестах я хочу протестировать эти отчеты с использованием разных наборов данных и языков и узнать , есть ли перекрывающий текст. На данный момент модуль тестирует только экспорт PDF-файлов для каждой комбинации, которую я хочу протестировать, и кто-то должен вручную просмотреть их. Я бы хотел автоматизировать это.

ответ

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 балла) образуют прямоугольник. Но для диагональных текстов или перекошенных символов углы глифов представляют собой четырехугольную форму, поэтому вам нужно реализовать более сложную процедуру пересечения
- тестирование перекрытия может быть дополнительно отполировано для обеспечения малой степени перекрытия, допустим, 2 символа перекрываются, если пересечение больше X% от области символов. Вот почему метод GetPageOverlaps возвращает коллекцию парных прямоугольников, поэтому их можно обработать, если необходимо.

Отказ от ответственности: Я работаю в компании, которая разрабатывает библиотеку XFINIUM.PDF.

+0

Обратите внимание, что вам, вероятно, придется разработать стратегию борьбы с [kerning] (https://en.wikipedia.org/wiki/Kerning), чтобы избежать ложных срабатываний. – colinmac