2017-02-03 5 views
1

В моем проекте я застрял в необходимости разбирать PDF-файл, содержащий некоторые символы, отображаемые шрифтами Type3. Итак, мне нужно сделать, чтобы эти символы были добавлены в BufferedImage для дальнейшей обработки.Render Type3 шрифт как изображение с помощью PDFBox

Я не уверен, если я смотрю на правильном пути, но я пытаюсь получить 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).

Я смотрю в правильном направлении и что мне делать с этими данными? Если нет, есть ли другие инструменты, которые могут решить такую ​​проблему?

+0

Помогает ли мой ответ? Если нет, просьба поделиться образцом PDF-реферала для ваших шрифтов Type 3. Как уже упоминалось в моем ответе, а затем обсуждался с @Tilman в комментариях к нему, могут существовать варианты шрифтов Type 3 для обработки по-разному ... – mkl

ответ

1

К сожалению, PDFBox из коробки не предоставляет класс для визуализации содержимого произвольных XObjects (например, шрифт char 3), по крайней мере, насколько я могу видеть.

Но он предоставляет класс для рендеринга полных страниц PDF; таким образом, для отображения заданного глифа шрифта 3-го типа можно просто создать страницу, содержащую только этот глиф, и отобразить эту временную страницу!

Предполагая, что, например, шрифт типа 3 определяется на первой странице PDDocument document и имеет имя 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)


Учитывая textPosition переменные в коде OP, он вполне вероятна попытка это из текста выписки ион используется кейс. Таким образом, ему придется либо предварительно генерировать растровые изображения, как указано выше, и просто искать их по имени или адаптировать код в соответствии с доступной информацией в своем прецеденте (например, у него может не быть оригинальной страницы под рукой, только шрифт объект, в этом случае он не может копировать ресурсы исходной страницы, но вместо этого может создать новый объект ресурсов и добавить к нему объект шрифта).


К сожалению, ОП не предоставил образец PDF. Таким образом, я использовал один из другого вопроса переполнения стека, 4700198773.pdf от extract text with custom font result non readble для моего теста. Очевидно, что могут остаться проблемы с собственными файлами OP.

+0

напоминает мне, что у меня был код для PDFDebugger, который был несовместим. Он использует ту же стратегию (создайте PDF). У вашего есть один небольшой недостаток: он не будет работать, когда BBox очень мал. См. Шрифт T4 в файле из PDFBOX-2959 (это очень странный файл, я должен признать) –

+0

* «[PDFBOX-2959] (https://issues.apache.org/jira/browse/PDFBOX-2959) «* - забавное животное, но действительное на первый взгляд. Хорошо, для таких случаев нужно проанализировать поток контента и определить фактический граничный поле, если использованный выше метод приводит к вырожденному граничному ящику. Это может фактически сочетаться с разбором в 'charProc.getGlyphBBox()' и поэтому не создавать слишком много дополнительных накладных расходов.Реализация оставлена ​​в качестве упражнения для читателя ...;) – mkl

+0

@TilmanHausherr Шрифты Type3 в [sdnlist.pdf] (https://www.treasury.gov/ofac/downloads/sdnlist.pdf), на которые ссылается [this вопрос] (http://stackoverflow.com/q/42073700/1729265) также не удается использовать метод выше. Ну, ну, OP должен сказать, все ли работает хорошо для его файлов ... – mkl

 Смежные вопросы

  • Нет связанных вопросов^_^