PDFBox 1.8 PrintTextLocations多页文本位置位置高度错误pdf [英] PDFBox 1.8 PrintTextLocations wrong TextPosition height for a multi page pdf

查看:30
本文介绍了PDFBox 1.8 PrintTextLocations多页文本位置位置高度错误pdf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行PDFBox提供的示例,以获取每个TextPosition的宽度/高度。当我通过一页pdf时,它会给我准确的结果。但如果我使用多页pdf,我得到的高度不正确。

这是我做的实验,我拿了一个5页的pdf作为参数传入(为每个文本位置获取了错误的高度)。接下来,我使用MacOSX预览将相同的pdf分成5个单页pdf,然后逐一浏览(我得到了正确的高度)。

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,缩放比例:12.0]6

字符串[x:58.6,y:741.2,高度:33.480003,间距:2.64,宽度:6.6360016,缩放比例:12.0]1

字符串[x:58.6,y:753.4,高度:33.480003,间距:2.64,宽度:6.6360016,缩放比例:12.0]2

输出狙击手-1页pdf

字符串[x:58.5,y:692.2,高度:5.55,间距:2.64,宽度:6.6480026,缩放比例:12.0]6

字符串[x:58.6,y:741.2,高度:5.55,间距:2.64,宽度:6.6480026,缩放比例:12.0]1

字符串[x:58.6,y:753.4,高度:5.55,间距:2.64,宽度:6.6480026,缩放比例:12.0]2

有人知道为什么我们在这种情况下得到不一致的结果吗?我是否遗漏了什么设置?

谢谢你的帮助。

这是另一个测试文件 wrong height pdf - 3 pages 这里是我得到的输出

字符串[x:90.0,y:83.28003,高度:33.480003,间距:5.8497605,宽度:7.248001,缩放比例:12.0]V

字符串[x:97.242,y:83.28003,高度:33.480003,空格:5.8497605,宽度:5.856003,y比例:12.0]e

字符串[x:103.095604,y:83.28003,高度:33.480003,间距:5.8497605,宽度:4.9680023,缩放比例:12.0]r

字符串[x:108.0588,y:83.28003,高度:33.480003,空格:5.8497605,宽度:6.0479965,y比例:12.0]y

字符串[x:116.748,y:83.28003,高度:33.480003,空格:5.8497605,宽度:5.9520035,y比例:12.0%S

字符串[x:122.7012,y:83.28003,高度:33.480003,间距:5.8497605,宽度:3.3359985,缩放比例:12.0]i

字符串[x:126.034805,y:83.28003,高度:33.480003,间距:5.8497605,宽度:9.983994,缩放比例:12.0]m

字符串[x:136.01881,y:83.28003,高度:33.480003,间距:5.8497605,宽度:6.671997,缩放比例:12.0p]p

字符串[x:142.6932,y:83.28003,高度:33.480003,间距:5.8497605,宽度:3.251999,缩放比例:12.0]l

字符串[x:145.9512,y:83.28003,高度:33.480003,空格:5.8497605,宽度:5.856003,y比例:12.0]e

字符串[x:154.4472,y:83.28003,高度:33.480003,间距:5.8497605,宽度:7.9440002,缩放比例:12.0]D

字符串[x:162.38641,y:83.28003,高度:33.480003,间距:5.8497605,宽度:6.371994,缩放比例:12.0]o

字符串[x:168.75601,y:83.28003,高度:33.480003,间距:5.8497605,宽度:5.2920074,y比例:12.0c]c 字符串[x:174.0468,y:83.28003,高度:33.480003,间距:5.8497605,宽度:6.624008,y比例:12.0u]u 字符串[x:180.6732,y:83.28003,高度:33.480003,间距:5.8497605,宽度:9.983994,y比例:12.0]m 字符串[x:190.6572,y:83.28003,高度:33.480003,间距:5.8497605,宽度:5.856003,y比例:12.0]e 字符串[x:196.5108,y:83.28003,高度:33.480003,间距:5.8497605,宽度:6.695999,y比例:12.0%n]n 字符串[x:203.20801,y:83.28003,高度:33.480003,间距:5.8497605,宽度:4.0559998,y比例:12.0t]t 已完成处理页面%0 完成添加页面%0 字符串[x:90.0,y:139.44,高度:33.480003,间距:5.8497605,宽度:6.816002,y比例:12.0]P

字符串[x:96.8148,y:139.44,高度:33.480003,间距:5.8497605,宽度:5.856003,缩放比例:12.0]a

字符串[x:102.6696,y:139.44,高度:33.480003,间距:5.8497605,宽度:5.9280014,y比例:12.0g]g

字符串[x:108.5964,y:139.44,高度:33.480003,空格:5.8497605,宽度:5.856003,y比例:12.0]e

字符串[x:117.090004,y:139.44,高度:33.480003,间距:5.8497605,宽度:6.6480026,缩放比例:12.0]2

字符串[x:126.375595,y:139.44,高度:33.480003,间距:5.8497605,宽度:6.371994,缩放比例:12.0]o

字符串[x:132.7464,y:139.44,高度:33.480003,间距:5.8497605,宽度:3.6360016,缩放比例:12.0%f

字符串[x:139.0312,y:139.44,高度:33.480003,间距:5.8497605,宽度:9.983994,缩放比例:12.0]m

字符串[x:149.0152,y:139.44,高度:33.480003,间距:5.8497605,宽度:3.3359985,缩放比例:12.0]i

字符串[x:152.3488,y:139.44,高度:33.480003,间距:5.8497605,宽度:6.695999,缩放比例:12.0]n

字符串[x:159.046,y:139.44,高度:33.480003,间距:5.8497605,宽度:3.3359985,缩放比例:12.0]i

字符串[x:162.37961,y:139.44,高度:33.480003,间距:5.8497605,宽度:9.983994,缩放比例:12.0]m

字符串[x:172.3636,y:139.44,高度:33.480003,间距:5.8497605,宽度:5.856003,缩放比例:12.0]a

字符串[x:178.2232,y:139.44,高度:33.480003,间距:5.8497605,宽度:3.251999,缩放比例:12.0]l

字符串[x:181.4812,y:139.44,高度:33.480003,间距:5.8497605,宽度:3.3359985,缩放比例:12.0]i

字符串[x:184.8148,y:139.44,高度:33.480003,空格:5.8497605,宽度:5.1600037,y比例:12.0s]s

字符串[x:189.9712,y:139.44,高度:33.480003,间距:5.8497605,宽度:9.983994,缩放比例:12.0]m

已完成处理第1页 完成添加第1页 字符串[x:90.0,y:266.15997,高度:33.480003,间距:5.8497605,宽度:6.816002,y比例:12.0]P

字符串[x:96.8148,y:266.15997,高度:33.480003,间距:5.8497605,宽度:5.856003,缩放比例:12.0]a

字符串[x:102.6696,y:266.15997,高度:33.480003,间距:5.8497605,宽度:5.9280014,y比例:12.0g]g

字符串[x:108.5964,y:266.15997,高度:33.480003,空格:5.8497605,宽度:5.856003,y比例:12.0]e

字符串[x:117.090004,y:266.15997,高度:33.480003,间距:5.8497605,宽度:6.6480026,缩放比例:12.0]3

字符串[x:126.375595,y:266.15997,高度:33.480003,间距:5.8497605,宽度:6.371994,缩放比例:12.0]o

字符串[x:132.7464,y:266.15997,高度:33.480003,间距:5.8497605,宽度:7.548004,缩放比例:12.0]K

字符串[x:140.3052,y:266.15997,高度:33.480003,间距:5.8497605,宽度:5.856003,缩放比例:12.0]a

字符串[x:146.16,y:266.15997,高度:33.480003,空格:5.8497605,宽度:6.048004,y比例:12.0]y

字符串[x:152.2068,y:266.15997,高度:33.480003,间距:5.8497605,宽度:5.0639954,缩放比例:12.0]?

已完成处理第2页 完成添加第2页

推荐答案

在确定已解析字形的高度时(使用所讨论的字体对象的getFontHeight方法),PDFBox首先检查手头是否有单个字形的字体度量。它在这里只知道AFM Type 1字体指标;由于您的字体是True Type字体,因此,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接下来会尝试使用大写字母高度,然后是Ascant,最后是/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的文本TouchUp工具,您会看到以下内容:

竖线就是光标!所以Acrobat也认为字体太大了。

遗憾的是,您没有提供通过使用MacOSX预览拆分从您的样本创建的单页pdf。因此,我不知道为什么你之后会得到更多现实的信息。但显然,预览以某种方式更改了字体信息,因为高度值过大的原因与文档有多页或只有一页无关。

这篇关于PDFBox 1.8 PrintTextLocations多页文本位置位置高度错误pdf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆