1

PDFBox で提供されているサンプルを実行して、各 TextPosition の幅/高さを取得しています。1ページのpdfを渡すと、正確な結果が得られます。しかし、複数ページの PDF を使用すると、高さが正しくありません。

これは私が行った実験です。5 ページの pdf を取得し、引数として渡しました (各 TextPosition の高さが間違っていました)。次に、MacOSX Preview を使用して同じ pdf を 5 つの単一ページの pdf に分割し、各ページを 1 つずつ渡しました (正しい高さを取得します)。

package printtextlocations;

import java.io.*;
import org.apache.pdfbox.exceptions.InvalidPasswordException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.util.PDFTextStripper;
import org.apache.pdfbox.util.TextPosition;

import java.io.IOException;
import java.util.List;

public class PrintTextLocations extends PDFTextStripper {

    public PrintTextLocations() throws IOException {
        super.setSortByPosition(true);
    }

    public static void main(String[] args) throws Exception {

        PDDocument document = null;
        try {
            File input = new File("C:\\path\\to\\PDF.pdf");
            document = PDDocument.load(input);
            if (document.isEncrypted()) {
                try {
                    document.decrypt("");
                } catch (InvalidPasswordException e) {
                    System.err.println("Error: Document is encrypted with a password.");
                    System.exit(1);
                }
            }
            PrintTextLocations printer = new PrintTextLocations();
            List allPages = document.getDocumentCatalog().getAllPages();
            for (int i = 0; i < allPages.size(); i++) {
                PDPage page = (PDPage) allPages.get(i);
                System.out.println("Processing page: " + i);
                PDStream contents = page.getContents();
                if (contents != null) {
                    printer.processStream(page, page.findResources(), page.getContents().getStream());
                }
            }
        } finally {
            if (document != null) {
                document.close();
            }
        }
    }

    /**
     * @param text The text to be processed
     */
    @Override
    protected void processTextPosition(TextPosition text) {
        System.out.println(" String [x: " + text.getXDirAdj() + ", y: "
            + text.getY() + ", height:" + text.getHeightDir()
            + ", space: " + text.getWidthOfSpace() + ", width: "
            + text.getWidthDirAdj() + ", yScale: " + text.getYScale() + "]"
            + text.getCharacter());
    }
}

出力スニペット - 5 ページの pdf

文字列 [x: 58.500004、y: 692.2、高さ:33.480003、スペース: 2.64、幅: 6.635998、yScale: 12.0]6

文字列 [x: 58.6、y: 741.2、高さ:33.480003、スペース: 2.64、幅: 6.6360016、yScale: 12.0]1

文字列 [x: 58.6, y:753.4, 高さ:33.480003, スペース: 2.64, 幅: 6.6360016, yScale: 12.0]2

出力スニッパー - 1 ページの PDF

文字列 [x: 58.5, y: 692.2, 高さ:5.55, スペース: 2.64, 幅: 6.6480026, yScale: 12.0]6

文字列 [x: 58.6, y: 741.2, 高さ:5.55, スペース: 2.64, 幅: 6.6480026, yScale: 12.0]1

文字列 [x: 58.6, y: 753.4, 高さ:5.55, スペース: 2.64, 幅: 6.6480026, yScale: 12.0]2

この場合、一貫性のない結果が得られる理由を知っている人はいますか? 不足している設定はありますか?

助けてくれてありがとう。

これは別のテストファイルの 間違った高さのpdfです - 3ページ とここに私が得る出力があります

文字列 [x: 90.0、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 7.248001、yScale: 12.0]V

文字列 [x: 97.242、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale: 12.0]e

文字列 [x: 103.095604, y: 83.28003, 高さ:33.480003, スペース: 5.8497605, 幅:4.9680023,yScale:12.0]r

文字列 [x: 108.0588、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 6.0479965、yScale:12.0]y

文字列 [x: 116.748, y: 83.28003, 高さ:33.480003, スペース: 5.8497605, 幅: 5.9520035, yScale: 12.0]S

文字列 [x: 122.7012、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 3.3359985、yScale:12.0]i

文字列 [x: 126.034805, y: 83.28003, 高さ:33.480003, スペース: 5.8497605, 幅: 9.983994,yScale:12.0]m

文字列 [x: 136.01881、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 6.671997、yScale:12.0]p

文字列 [x: 142.6932、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 3.251999、yScale: 12.0]l

文字列 [x: 145.9512、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale: 12.0]e

文字列 [x: 154.4472、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 7.9440002、yScale:12.0]D

文字列 [x: 162.38641、y: 83.28003、高さ:33.480003、スペース: 5.8497605、幅: 6.371994、yScale:12.0]o

文字列 [x: 168.75601, y: 83.28003, 高さ:33.480003, スペース: 5.8497605, 幅: 5.2920074, yScale: 12.0]c 文字列 [x: 174.0468, y: 83.28003, 高さ:33.480003, スペース: 5.84:0070 : 12.0]u 文字列 [x: 180.6732, y: 83.28003, 高さ:33.480003, スペース: 5.8497605, 幅: 9.983994, yScale: 12.0]m 文字列 [x: 190.6572, y: 83.28003, 高さ:33.480003, 4 幅9 5.50 : 5.856003, yScale: 12.0]e String [x: 196.5108, y: 83.28003, height:33.480003, space: 5.8497605, width: 6.695999, yScale: 12.0]n String [x: 203.20801, y: 0:0:303.4, height スペース: 5.8497605, 幅: 4.0559998, yScale: 12.0]t ページ 0 の処理完了 ページ 0 の追加 ページ 0 文字列 [x: 90.0, y: 139.44, 高さ:33.480003, スペース: 5.8497605, 幅: 6.816002, yScale: 12.0]P

文字列 [x: 96.8148、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale: 12.0]a

文字列 [x: 102.6696, y: 139.44, 高さ:33.480003, スペース: 5.8497605, 幅: 5.9280014, yScale: 12.0]g

文字列 [x: 108.5964、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale: 12.0]e

文字列 [x: 117.090004、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 6.6480026、yScale:12.0]2

文字列 [x: 126.375595、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 6.371994、yScale: 12.0]o

文字列 [x: 132.7464、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 3.6360016、yScale: 12.0]f

文字列 [x: 139.0312, y: 139.44, 高さ:33.480003, スペース: 5.8497605, 幅: 9.983994, yScale: 12.0]m

文字列 [x: 149.0152、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 3.3359985、yScale: 12.0]i

文字列 [x: 152.3488、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 6.695999、yScale: 12.0]n

文字列 [x: 159.046、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 3.3359985、yScale: 12.0]i

文字列 [x: 162.37961, y: 139.44, 高さ:33.480003, スペース: 5.8497605, 幅: 9.983994, yScale: 12.0]m

文字列 [x: 172.3636、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale: 12.0]a

文字列 [x: 178.2232、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 3.251999、yScale: 12.0]l

文字列 [x: 181.4812、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 3.3359985、yScale: 12.0]i

文字列 [x: 184.8148、y: 139.44、高さ:33.480003、スペース: 5.8497605、幅: 5.1600037、yScale: 12.0]s

文字列 [x: 189.9712, y: 139.44, 高さ:33.480003, スペース: 5.8497605, 幅: 9.983994, yScale: 12.0]m

ページ 1 の処理完了 ページ 1 の追加完了 文字列 [x: 90.0, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅: 6.816002, yScale: 12.0]P

文字列 [x: 96.8148、y: 266.15997、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale:12.0]a

文字列 [x: 102.6696, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅: 5.9280014,yScale:12.0]g

文字列 [x: 108.5964、y: 266.15997、高さ:33.480003、スペース: 5.8497605、幅: 5.856003、yScale:12.0]e

文字列 [x: 117.090004、y: 266.15997、高さ:33.480003、スペース: 5.8497605、幅:6.6480026、yScale:12.0]3

文字列 [x: 126.375595, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅:6.371994,yScale:12.0]o

文字列 [x: 132.7464, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅: 7.548004,yScale:12.0]K

文字列 [x: 140.3052, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅: 5.856003,yScale:12.0]a

文字列 [x: 146.16, y: 266.15997, 高さ:33.480003, スペース: 5.8497605, 幅: 6.048004, yScale: 12.0]y

文字列 [x: 152.2068、y: 266.15997、高さ:33.480003、スペース: 5.8497605、幅: 5.0639954、yScale:12.0]?

ページ 2 の処理完了 ページ 2 の追加

4

2 に答える 2

4

解析されたグリフの高さを (getFontHeight問題のフォント オブジェクトのメソッドを使用して) 決定するとき、PDFBox は最初に個々のグリフのフォント メトリックが手元にあるかどうかをチェックします。ここでは、AFM タイプ 1 フォント メトリックのみを認識します。あなたのフォントは真のタイプのフォントであるため、PDFBoxにはそのようなメトリックはありません。

このような場合、フォント記述子から一般的なフォント メトリックを取得しようとします。ドキュメント内のフォントのフォント記述子は次のようになります。

21 0 obj <<
    /Type /FontDescriptor
    /FontName /GLDXOZ+Cambria
    /Flags 4
    /FontBBox [-1475 -2463 2867 3117]
    /ItalicAngle 0
    /Ascent 950
    /Descent -222
    /CapHeight 667
    /StemV 0
    /XHeight 467
    /AvgWidth 615
    /MaxWidth 2919
    /FontFile2 24 0 R
>>
endobj

検査する最初の記述子エントリはフォント境界ボックス ( /FontBBoxエントリ) であり、存在する場合は、その半分の高さを平均フォント高として取得します。

あなたの場合、フォントの境界ボックスは、フォントのグリフに比べて非常に大きいです。垂直方向は -2463 から 3117 までです!!

一方、大文字の高さ ( /CapHeightエントリ、ベースラインから測定した平坦な大文字の上部の垂直座標) はわずか 667 であり、アセント ( /Ascentグリフが到達するベースラインからの最大高さ) です。このフォントでは; アクセント付き文字のグリフの高さは除外されます) わずか 950.これは、なぜそのフォントにそのようなフォント境界ボックスがあるのか​​ 疑問に思います...

フォント境界ボックスがなければ、PDFBox は次に大文字の高さ、次にアセント、そして最終的に/XHeight - /Descentを使用しようとします。これらのそれぞれは妥当な値になりますが、その境界ボックスがあるため、PDFBox は大きすぎる値を想定します。

問題のコードは次のようにコメントされています

// the following values are all more or less accurate
// at least all are average values. Maybe we'll find
// another way to get those value for every single glyph
// in the future if needed

PDFBox が上昇率などではなく境界ボックスからの平均高さを推測することを好む理由はわかりませんが、そのフォントのテキストが巨大であると想定するソフトウェアはそれだけではありません。たとえば、Adobe Acrobat のテキスト タッチアップ ツールを使用すると、次のように表示されます。

タッチアップツールの動作

縦棒がカーソル!そのため、Acrobat もフォントが巨大であると考えています。

残念ながら、サンプルから MacOSX Preview で分割して作成した単一ページの PDF は提供されていません。したがって、その後、なぜより現実的な情報が得られるのかわかりません。ただし、高さの値が巨大な理由は、ドキュメントが複数のページまたは 1 つしかないこととは関係がないため、Preview は何らかの方法でフォント情報を変更することは明らかです。

于 2013-05-16T10:12:39.417 に答える