2016-02-19 82 views
0

在提取的話,在這個例子中的位置: http://www.dertour.de/static/agb/2015/sommer/DER_Deutschland_So15.pdf 與iTextSharp的5.5.8iTextSharp的 - 不正確的文本位置

我得到「不正確」座標一些話。例如,在第一段的第17行:'gehen oder im Widerspruch zur Reiseaus-' ,單詞的左側頂部位置的x值是118,217,296,350,524,587。只有第一個值似乎是正確的(118,208,277,320,487,540)。 'gehen'和'oder'之間空格字符右下角的x值是208,這看起來是正確的,而且似乎是「oder」這個單詞的正確x-pos。也許它與段落的填充模式有關,但我不確定我應該執行哪些操作來獲得正確的座標。

我正在使用LocationTextExtractionStrategy並將字位置計算爲300 dpi座標系。

 public override void RenderText(TextRenderInfo renderInfo) 
     { 
      // for the provided example 
      // uUnit = 1 
      // originX = 33.862 
      // originY = 33.555 
      // dpi = 300 

      // above values where calculated with code: 
      // PdfNumber userUnit = pageDict.GetAsNumber(PdfName.USERUNIT); 
      // if (userUnit != null) 
      // { 
      // uUnit = userUnit.FloatValue; 
      // } 
      // Rectangle dim = reader.GetPageSize(i); 
      // float originX = dim.Left; 
      // float originY = dim.Bottom; 


      // calculate coordinates: 
      renderInfo.GetText(); 
      LineSegment segment = renderInfo.GetBaseline(); 
      List<TextRenderInfo> charInfo = renderInfo.GetCharacterRenderInfos().ToList(); 

      foreach (TextRenderInfo item in charInfo) 
      { 
       LineSegment char_segment = item.GetBaseline(); 

       int char_left = (int)Math.Round((char_segment.GetStartPoint()[0] - originX) * dpi * uUnit/72.0f); 
       int char_top = (int)Math.Round((item.GetAscentLine().GetEndPoint()[1] - originY) * dpi * uUnit/72.0f); 
       int char_right = (int)Math.Round((char_segment.GetEndPoint()[0] - originX) * dpi * uUnit/72.0f); 
       int char_bottom = (int)Math.Round((item.GetDescentLine().GetStartPoint()[1] - originY) * dpi * uUnit/72.0f); 
      } 
    } 

回答

1

實際上就是在iText的& iTextSharp的一個錯誤:

與極不準確X座標系是那些針對其大wordspacing值被設置,例如您行:

0.2861 Tw T* 
[<0047004500480045004E0000>-286<004F0044004500520000>-286<0049004D0000>-231<003700490044004500520053005000520055004300480000>-286<005A005500520000>-286<00320045004900530045004100550053000D>]TJ 

(即0.2861論據Tw大)

根據每個單詞映射到空格字符結束的ToUnicode地圖有問題的0000的字體。因此,iText的計算X座標的時候,這裏增加了字間距值,因爲根據PDF規範ISO 32000-1

字間距的工作方式相同字符間距,但僅適用於ASCII空格字符

(段的第一句9.3.3字間距)

遺憾的是它並沒有考慮到

使用 簡單字體或將代碼32定義爲單字節代碼的複合字體時,字間距應適用於字符串中出現的每個單字節字符代碼32。它不適用於多字節代碼中字節值32的出現 。

(最後一句9.3節。3字間距)

在高於0000,因此,字間距不能即使它被映射到空格字符施加因爲

  1. 所討論的字體編碼是純的多字節和
  2. 即使在單字節編碼空格字符的情況下,字間距也僅適用於單字節代碼 32,而不是僅通過ASCII映射到空間字符的代碼德32

通常這不是文本提取,一般PDF生成器使用該多字節編碼的編碼空格字符都知道,字間距並不適用於他們,因此,不要在一個問題將字間距從其默認的0值改變,所以這裏的iText錯誤沒有任何危害。字間距指令的使用通常指示使用將單字節代碼32映射到空格字符的字體。

另一方面,您的PDF看起來似乎還沒有在頭腦中創建這個事實,它看起來像首先設置了字間距(0.2861 Tw),並且在認識到它沒有區別之後,顯式差距已被添加(TJ指令中的-286)。 (或者說是有問題的PDF生成器的發展歷史的一部分。)

請注意,在TJ參數正值意味着向左移位,所以負值(如聲稱對-286上文)確實擴大或增加空白:

陣列TJ顯示的一個或多個文本串,允許個人字形的定位。數組中的每個元素應該是一個字符串或一個數字。如果該元素是一個字符串,則該運算符應顯示該字符串。如果是數字,則操作員應按該數量調整文本位置;也就是說,它應該翻譯文本矩陣,T m。編號應以文本空間單位的千分之一表示(見第9.4.4節「文本空間詳細信息」)。根據寫入模式,該數量應從當前水平或垂直座標中減去。在默認座標系中,正向調整的效果是將下一個字形向左或向下移動給定量。圖46顯示了將偏移量傳遞給TJ的一個示例。

(表109 - 在ISO 32000-1文本顯示運營商)

+1

你誤解負值:他們這樣做拉開差距。 – mkl

+1

如上所述,由於我們有嚴格的雙字節編碼,所以在這裏任何地方都不應用字間距*,因此沒有單字節32編碼空間。 – mkl