java - 使用 PDFBox 将 Type3 字体字符渲染为图像

标签 java pdf pdfbox

在我的项目中,我必须解析 PDF 文件,其中包含一些由 Type3 字体呈现的字符。所以,我需要做的就是将这些字符渲染到BufferedImage中进行进一步处理。

我不确定我是否以正确的方式查找,但我正在尝试获取此类字符的 PDType3CharProc:

PDType3Font font = (PDType3Font)textPosition.getFont();
PDType3CharProc charProc = font.getCharProc(textPosition.getCharacterCodes()[0]);

该过程的输入流包含以下数据:

54 0 1 -1 50 43 d1
q
49 0 0 44 1.1 -1.1 cm
BI
/W 49
/H 44
/BPC 1
/IM true
ID
<some binary data here>
EI
Q

但不幸的是,我不知道如何使用这些数据使用 PDFBox(或任何其他 Java 库)将字符渲染到图像中。

我的方向正确吗?我可以用这些数据做什么? 如果没有,还有其他工具可以解决这个问题吗?

最佳答案

不幸的是,开箱即用的 PDFBox 不提供一个类来呈现任意 XObject 的内容(如 type 3 字体字符过程),至少据我所知。

但它确实提供了一个用于渲染完整 PDF 页面的类;因此,要呈现给定的 3 类字体字形,只需创建一个仅包含该字形的页面并呈现此临时页面即可!

假设,例如,类型 3 字体定义在 PDDocument 文档 的第一页上,并且名称为 F1,则其所有字符过程都可以像这样呈现:

PDPage page = document.getPage(0);
PDResources pageResources = page.getResources();
COSName f1Name = COSName.getPDFName("F1");
PDType3Font fontF1 = (PDType3Font) pageResources.getFont(f1Name);
Map<String, Integer> f1NameToCode = fontF1.getEncoding().getNameToCodeMap();

COSDictionary charProcsDictionary = fontF1.getCharProcs();
for (COSName key : charProcsDictionary.keySet())
{
    COSStream stream = (COSStream) charProcsDictionary.getDictionaryObject(key);
    PDType3CharProc charProc = new PDType3CharProc(fontF1, stream);
    PDRectangle bbox = charProc.getGlyphBBox();
    if (bbox == null)
        bbox = charProc.getBBox();
    Integer code = f1NameToCode.get(key.getName());

    if (code != null)
    {
        PDDocument charDocument = new PDDocument();
        PDPage charPage = new PDPage(bbox);
        charDocument.addPage(charPage);
        charPage.setResources(pageResources);
        PDPageContentStream charContentStream = new PDPageContentStream(charDocument, charPage);
        charContentStream.beginText();
        charContentStream.setFont(fontF1, bbox.getHeight());
        charContentStream.getOutput().write(String.format("<%2X> Tj\n", code).getBytes());
        charContentStream.endText();
        charContentStream.close();

        File result = new File(RESULT_FOLDER, String.format("4700198773-%s-%s.png", key.getName(), code));
        PDFRenderer renderer = new PDFRenderer(charDocument);
        BufferedImage image = renderer.renderImageWithDPI(0, 96);
        ImageIO.write(image, "PNG", result);
        charDocument.close();
    }
}

( RenderType3Character.java 测试方法 testRender4700198773)

<小时/>

考虑到OP代码中的textPosition变量,他很可能从文本提取用例中尝试这样做。因此,他必须像上面那样预先生成位图,然后简单地按名称查找它们,或者调整代码以匹配他的用例中的可用信息(例如,他手头可能没有原始页面,只有字体对象;在这种情况下,他无法复制原始页面的资源,而是可以创建一个新的资源对象并向其中添加字体对象)。

<小时/>

不幸的是,OP 没有提供 PDF 样本。因此,我使用了另一个堆栈溢出问题中的一个,4700198773.pdf来自extract text with custom font result non readble为了我的测试。 OP自己的文件显然可能仍然存在问题。

关于java - 使用 PDFBox 将 Type3 字体字符渲染为图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42032729/

相关文章:

java - 如果pdf是从java代码生成的,如何解决损坏的pdf文件?

java - 波斯语文档的 PDFBOX

java - PDFBox : Extraction of data from table

JavaFX 流量模拟转换

java - 如何从日期/时间选择器对话框获取日期和时间并显示它?

java - 如何从java字符串for循环创建json数组

java - eclipse中struts2 mysql连接错误

邮件中的 Swift pdf 附件

javascript - 在 MS Edge 中执行 PDF 文件中的 JavaScript

java - PDF框。 Java : How to print only one page of PDF instead of full document?