如何使用PDFBOX确定文本的人工粗体样式、人工斜体样式和人工轮廓样式

2024-05-03

我正在使用 PDFBox 来验证 pdf 文档。 检查 PDF 中存在的以下类型的文本有一定要求

  • 人工粗体样式文本
  • 人造斜体样式文本。
  • 人工轮廓样式文本

我在 PDFBOX api 列表中进行了搜索,但找不到此类 api。

任何人都可以帮助我并告诉我如何使用 PDFBOX 确定 PDF 中存在的不同类型的人工字体/文本样式。


一般过程和 PDFBox 问题

理论上,应该从派生一个类开始PDFTextStripper并重写它的方法:

/**
 * Write a Java string to the output stream. The default implementation will ignore the <code>textPositions</code>
 * and just calls {@link #writeString(String)}.
 *
 * @param text The text to write to the stream.
 * @param textPositions The TextPositions belonging to the text.
 * @throws IOException If there is an error when writing the text.
 */
protected void writeString(String text, List<TextPosition> textPositions) throws IOException
{
    writeString(text);
}

然后你的覆盖应该使用List<TextPosition> textPositions而不是String text; each TextPosition本质上代表单个字母以及绘制该字母时激活的图形状态的信息。

不幸的是textPositions列表确实not包含当前版本 1.8.3 中的正确内容。例如。对于“这是普通文本”这一行。从您的 PDF 中获取方法writeString被调用四次,对于字符串“This”、“is”、“normal”和“text”各调用一次。不幸的是textPositions每次列表包含TextPosition最后一个字符串“text”的字母的实例。

这实际上证明已经被识别为PDFBox问题PDFBOX-1804 https://issues.apache.org/jira/browse/PDFBOX-1804同时,该问题已在 1.8.4 和 2.0.0 版本中得到解决。

话虽如此,一旦您有了修复后的 PDFBox 版本,您就可以检查一些人工样式,如下所示:

人工斜体文本

该文本样式在页面内容中创建如下:

BT
/F0 1 Tf
24 0 5.10137 24 66 695.5877 Tm
0 Tr
[<03>]TJ
...

相关部分发生在设置文本矩阵中Tm。 5.10137 是文本剪切的因子。

当您检查一个TextPosition textPosition如上所述,您可以使用以下方式查询该值

textPosition.getTextPos().getValue(1, 0)

如果该值相应地大于 0.0,则会出现人造斜体。如果它相对小于 0.0,则会出现人工向后斜体。

人工粗体或轮廓文本

这些人造风格使用不同渲染模式的双打印字母;例如大写“T”,如果是粗体:

0 0 0 1 k
...
BT
/F0 1 Tf 
24 0 0 24 66.36 729.86 Tm 
<03>Tj 
4 M 0.72 w 
0 0 Td 
1 Tr 
0 0 0 1 K
<03>Tj
ET

(即首先以常规模式绘制字母,填充字母区域,然后以轮廓模式绘制,沿字母边框绘制一条线,均为黑色,CMYK 0, 0, 0, 1;这留下了字比较粗。)

如果是大纲:

BT
/F0 1 Tf
24 0 0 24 66 661.75 Tm
0 0 0 0 k
<03>Tj
/GS1 gs
4 M 0.288 w 
0 0 Td
1 Tr
0 0 0 1 K
<03>Tj
ET

(即首先以常规模式白色绘制字母,CMYK 0, 0, 0, 0,填充字母区域,然后以轮廓模式绘制,沿字母边框绘制一条线,以黑色,CMYK 0, 0, 0 , 1;这会留下白底黑字轮廓的印象。)

不幸的是PDFBoxPDFTextStripper不跟踪文本渲染模式。此外,它显式地删除在大约相同位置出现的重复字符。因此,识别这些人为风格的任务并不重要。

如果你真的需要这样做,你就必须改变TextPosition还包含渲染模式,PDFStreamEngine将其添加到生成的TextPosition实例,以及PDFTextStripper to not删除重复的字形processTextPosition.

更正

I wrote

不幸的是PDFBoxPDFTextStripper不跟踪文本渲染模式。

这并不完全正确,你可以找到current渲染模式使用getGraphicsState().getTextState().getRenderingMode()。这意味着在processTextPosition您确实有可用的渲染模式,并且可以尝试存储给定的渲染模式(和颜色!)信息TextPosition某处,例如在一些Map<TextPosition, ...>,以供以后使用。

此外,它显式地删除在大约相同位置出现的重复字符。

您可以通过调用禁用此功能setSuppressDuplicateOverlappingText(false).

通过这两项更改,您也应该能够进行所需的测试来检查人工粗体和轮廓。

如果您尽早存储并检查样式,则后一种更改甚至可能没有必要processTextPosition.

如何检索渲染模式和颜色

正如中提到的更正确实如此is可以通过将信息收集在一个文件中来检索渲染模式和颜色信息processTextPosition覆盖。

对此,OP 评论说

抚摸和非抚摸颜色始终为黑色

起初这有点令人惊讶,但在查看之后PDFTextStripper.properties(从中初始化了文本提取期间支持的运算符),原因就清楚了:

# The following operators are not relevant to text extraction,
# so we can silently ignore them.
...
K
k

因此,在此上下文中,颜色设置运算符(尤其是本文档中的 CMYK 颜色的运算符)将被忽略!幸运的是,这些运算符的实现PageDrawer也可以在这种情况下使用。

因此,以下概念验证显示了如何检索所有必需的信息。

public class TextWithStateStripperSimple extends PDFTextStripper
{
    public TextWithStateStripperSimple() throws IOException {
        super();
        setSuppressDuplicateOverlappingText(false);
        registerOperatorProcessor("K", new org.apache.pdfbox.util.operator.SetStrokingCMYKColor());
        registerOperatorProcessor("k", new org.apache.pdfbox.util.operator.SetNonStrokingCMYKColor());
    }

    @Override
    protected void processTextPosition(TextPosition text)
    {
        renderingMode.put(text, getGraphicsState().getTextState().getRenderingMode());
        strokingColor.put(text, getGraphicsState().getStrokingColor());
        nonStrokingColor.put(text, getGraphicsState().getNonStrokingColor());

        super.processTextPosition(text);
    }

    Map<TextPosition, Integer> renderingMode = new HashMap<TextPosition, Integer>();
    Map<TextPosition, PDColorState> strokingColor = new HashMap<TextPosition, PDColorState>();
    Map<TextPosition, PDColorState> nonStrokingColor = new HashMap<TextPosition, PDColorState>();

    protected void writeString(String text, List<TextPosition> textPositions) throws IOException
    {
        writeString(text + '\n');

        for (TextPosition textPosition: textPositions)
        {
            StringBuilder textBuilder = new StringBuilder();
            textBuilder.append(textPosition.getCharacter())
                       .append(" - shear by ")
                       .append(textPosition.getTextPos().getValue(1, 0))
                       .append(" - ")
                       .append(textPosition.getX())
                       .append(" ")
                       .append(textPosition.getY())
                       .append(" - ")
                       .append(renderingMode.get(textPosition))
                       .append(" - ")
                       .append(toString(strokingColor.get(textPosition)))
                       .append(" - ")
                       .append(toString(nonStrokingColor.get(textPosition)))
                       .append('\n');
            writeString(textBuilder.toString());
        }
    }

    String toString(PDColorState colorState)
    {
        if (colorState == null)
            return "null";
        StringBuilder builder = new StringBuilder();
        for (float f: colorState.getColorSpaceValue())
        {
            builder.append(' ')
                   .append(f);
        }

        return builder.toString();
    }
}

使用这个你可以得到句点“.”在普通文本中为:

. - shear by 0.0 - 256.5701 88.6875 - 0 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 1.0

在人工粗体文本中,您会得到;

. - shear by 0.0 - 378.86 122.140015 - 0 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 1.0
. - shear by 0.0 - 378.86002 122.140015 - 1 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 1.0

人工斜体:

. - shear by 5.10137 - 327.121 156.4123 - 0 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 1.0

并在人工轮廓中:

. - shear by 0.0 - 357.25 190.25 - 0 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 0.0
. - shear by 0.0 - 357.25 190.25 - 1 -  0.0 0.0 0.0 1.0 -  0.0 0.0 0.0 0.0

现在,您已经了解了识别这些人工样式所需的所有信息。现在您只需分析数据即可。

顺便说一句,看看人工粗体的情况:坐标可能并不总是相同,而只是非常相似。因此,测试两个文本位置对象是否描述相同的位置需要一定的宽容度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用PDFBOX确定文本的人工粗体样式、人工斜体样式和人工轮廓样式 的相关文章

  • 创建仅在使用 PDFBox 打印时显示的水印(pdf 可选内容)

    我遇到过许多使用 PDFBox Layer Utility 的appendFormAsLayer 方法的示例 如下所示 Places the given form over the existing content of the indic
  • 使用 ImageMagick 和/或 GhostScript 将多页 PDF 转换为多个 JPG

    我正在尝试将多页 PDF 文件转换为一堆 JPEG PDF 中的每一页一个 我花了几个小时寻找如何做到这一点 最终我发现我需要安装 Ghostscript 所以我就这么做了 来自这个网站 http downloads ghostscript
  • 直接将 .aspx 转换为 .pdf [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 PHP 创建图表并导出为 PDF

    我正在寻找有关使用 PHP 创建图表的建议 我还希望能够将这些图表导出到 PDF 文档 我目前正在使用谷歌图表 但我不喜欢将我的所有信息发送到谷歌的想法 我更喜欢自己的托管解决方案 我见过很多 Flash 解决方案 但我不知道有什么方法可以
  • 使用 JavaScript 生成 PDF 文件

    我正在尝试将 XML 数据从网页转换为 PDF 文件 并且希望能够完全在 JavaScript 中完成此操作 我需要能够绘制文本 图像和简单的形状 我希望能够完全在浏览器中完成此操作 我刚刚写了一个名为jsPDF https github
  • 如何解决 PDFBox 没有 unicode 映射错误?

    我有一个现有的 PDF 文件 我想使用 python 脚本将其转换为 Excel 文件 目前正在使用PDFBox 但是存在多个类似以下错误 org apache pdfbox pdmodel font PDType0Font toUnico
  • 在 Flash Player 10 中打开 pdf

    我需要在 Flash Player 10 中打开 PDF 该 swf 不会在浏览器中运行 并且系统上不会有 adobe reader 程序 我需要知道是否可以在 Flash 播放器中打开 PDF 而无需以任何方式进行转换 我在谷歌上搜索了无
  • 如何在启用嵌入时间戳和 LTV 的情况下签署 PDF?

    我正在尝试签署启用了时间戳和 LTV 的 pdf 以便它在 Adob e Reader 中显示如下 在英语中 这意味着 签名包含嵌入的时间戳 和 签名启用了 LTV 这是我正在使用的代码 PrivateKey pk get pk from
  • 在 iPad 上显示 PDF 文档 - 颜色问题

    我为 iPad 构建了一个 PDF 阅读器 在将预览中的文档与模拟器和设备进行并排比较时 我注意到一些颜色问题 最好的形容就是颜色变得更加浓郁 近距离使用的相似颜色之间的任何差异都会变得更加明显 而所有颜色总体上看起来都更亮 尽管大肆宣传将
  • 当我使用 Mime 从 Python 发送时,Outlook 和 Thunderbird 未收到附件

    我试图在 python 中使用 MimeBase 发送一封带有附件的电子邮件 当我不使用 Thunderbird 或 Outlook 时 我什至可以发送电子邮件并接收 pdf 附件 并在浏览器中打开邮箱 mensagem MIMEMulti
  • 将jsp表导出到excel、word、pdf

    任何人都可以建议我任何库 jar 文件 我可以使用它们将我的表导出到 excel pdf word 请告诉我是否有任何可以在 jsp 中创建报告的库 还应该提到的是 您只需输出 HTML 表格并将响应类型设置为即可将表格导出到 Excela
  • PyFPDF在指定大小时无法添加页面

    在 pyfpdf 文档上据说可以在添加页面时指定格式 fpdf add page orientation format same False 但在指定格式时它给了我一个错误 error pdf add page format 1000 10
  • RowSpan 在 iTextSharp 中不起作用?

    我正在尝试将 Html 转换为 PDF 我正在使用 iTextSharp 我发现iTextSharp对CSS的支持不太好 事实上我认为 HtmlWorker 线程并不支持这一切 让我的问题更加复杂的是 iTextSharp 似乎也不支持 R
  • TCPDF 为一个文档中的不同页面设置不同的页眉

    有没有办法使文档中第一页的页眉徽标和第二页的页眉徽标不同 我认为在添加页面之间更改标题数据可能会解决问题 但在我的测试中 添加第一页后设置标题似乎没有效果 other stuff pdf gt setHeaderFont array PDF
  • 使用itext java库复制时pdf文件大小大大增加

    我正在尝试使用 Java 中的 itextpdf 库将现有的 pdf 文件复制到一些新文件中 我使用的是 itextpdf 5 5 10 版本 我在两种方式上都面临着不同的问题 PDFStamper 和 PdfCopy 当我使用 PDFSt
  • 在 iPhone 上搜索 PDF

    经过两天尝试使用 Quartz 从 PDF 中读取注释后 我成功做到了并且发布我的代码 https stackoverflow com questions 4080373 get pdf hyperlinks on ios with qua
  • 在 iOS 中,如何以编程方式填写 pdf 表单字段?

    我需要获取一个现有的 pdf 文件 并以编程方式填写带有文本的表单字段列表 然后保存 pdf 而不将其显示给用户 例如 如果 pdf 文件包含名为 LastName 和 FirstName 的字段 我想将 FirstName 的值设置为 L
  • Swift Siesta 访问响应原始数据

    我的 API 中有一个返回 PDF 文件内容的方法 如何在成功回调中获取响应的原始数据 所有午睡响应均以原始数据开始 以基础类型的形式Data 然后运行变压器管道 http bustoutsolutions github io siesta
  • 带有嵌入 Flash 视频的 PDF 示例?

    有谁知道我在哪里可以查看嵌入 Flash 视频的 PDF 示例 我知道问这个问题很愚蠢 因为你会认为任何面向技术的用户都应该能够使用谷歌找到一个 但我真的找不到 我的另一个问题是 使用 C 中的 API 将 Flash 视频嵌入 PDF 文
  • 在 Rails 中强制内联渲染 PDF 文档

    我正在编写一个从一组 XML 文件生成 PDF 文件的服务 正在正确生成 PDF 但是 每次我单击 查看 PDF 链接时 浏览器都会要求用户下载 PDF 文件 我需要 PDF 内联显示 就像任何常规 HTML 页面一样 我虽然我写的代码是正

随机推荐