Почему PDFBox возвращает размер изображения размером 0 x 0 - PullRequest
0 голосов
/ 29 мая 2018

Чтобы узнать фактический размер изображения в PDF, я использую PDFBox и следую тому, что описано в этом ответе .Поэтому в основном я вызываю

 // Computes the image actual location and dimensions
 PrintImageLocations renderer = new PrintImageLocations();

 for (int i = 0; i < pageLimit; ++i) {
        PDPage page = pdf.getPage(i);

        renderer.processPage(page);
 }

, а PrintImageLocations () взято из этого примера кода PDFBox .

Тем не менее, с документом PDF, который я использую для теста (сгенерированопо GPL Ghostscript 910 (ps2write) из изображения, найденного в Википедии ), размер сообщения составляет 0 x 0 (хотя PDF-файл можно импортировать в Gimp или Libre Office Draw).

Итак, я хотел бы знать, является ли код, который я сейчас использую, надежным или нет, чтобы найти размер изображения, и что может заставить его не найти правильный размер изображения?

PDF, используемый для этого теста , можно найти здесь

==========

Редактировать: После @Itai комментарияПохоже, что условие if ("Do".equals(operation)) не оценивается , поскольку такая операция не вызывается.Следовательно, processOperator из суперкласса вызывается.

Единственными вызываемыми операциями являются (я добавил System.err.println("Processing " + operation); перед условием в переопределенном методе processOperator):

Обработкаq Обработка cm Обработка gs Обработка q Обработка re Обработка W Обработка n Обработка rg Обработка re Обработка f Обработка cs Обработка scn Обработка re Обработка f Обработка Q Обработка Q

==========

Любые подсказки приветствуются,

1 Ответ

0 голосов
/ 29 мая 2018

Как вы уже узнали сами, причина вывода 0x0 заключается в том, что код из PrintImageLocations как есть вообще не может найти изображение.

PrintImageLocations не находит изображение, потому чтоон ищет только изображения, используемые в содержимом страницы и в форме XObjects (также вложенных), используемых в содержимом страницы.С другой стороны, в данном файле изображение рисуется внутри мозаичного содержимого Pattern , которое используется для заполнения области содержимого страницы.

Чтобы PDFBox мог найти это изображение, нам нужно немного расширить класс PrintImageLocations, чтобы также спускаться в потоки содержимого шаблона, например, так:

class PrintImageLocationsImproved extends PrintImageLocations {
    public PrintImageLocationsImproved() throws IOException {
        super();

        addOperator(new SetNonStrokingColor());
        addOperator(new SetNonStrokingColorN());
        addOperator(new SetNonStrokingDeviceCMYKColor());
        addOperator(new SetNonStrokingDeviceGrayColor());
        addOperator(new SetNonStrokingDeviceRGBColor());
        addOperator(new SetNonStrokingColorSpace());
    }

    @Override
    protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
        String operation = operator.getName();
        if (fillOperations.contains(operation)) {
            PDColor color = getGraphicsState().getNonStrokingColor();
            PDAbstractPattern pattern = getResources().getPattern(color.getPatternName());
            if (pattern instanceof PDTilingPattern) {
                processTilingPattern((PDTilingPattern) pattern, null, null);
            }
        }
        super.processOperator(operator, operands);
    }

    final List<String> fillOperations = Arrays.asList("f", "F", "f*", "b", "b*", "B", "B*");
}

( ExtractImageLocations внутренний класс PrintImageLocationsImproved)

Шаблон мозаики в документе, который используется, используется в качестве цвета шаблона для заливки, а не штриховки.Таким образом, PrintImageLocationsImproved должен зарегистрировать прослушиватели операторов для цветных операторов без штрихов, чтобы правильно обновить цвет заливки в графическом состоянии.

processOperator перед делегированием реализации PrintImageLocations теперь сначала проверяет, является лиоператором является операция fill .В этом случае он проверяет текущий цвет заливки.Если это цвет шаблона, processOperator инициирует обработку processTilingPattern, определенную в PDFStreamEngine, которая запускает вложенный анализ потока содержимого шаблона и, таким образом, в конечном итоге позволяет PrintImageLocationsImproved найти изображение.

ИспользованиеPrintImageLocationsImproved вот так

try (   PDDocument document = PDDocument.load(...)    )
{
    PrintImageLocations printer = new PrintImageLocationsImproved();
    int pageNum = 0;
    for( PDPage page : document.getPages() )
    {
        pageNum++;
        System.out.println( "Processing page: " + pageNum );
        printer.processPage(page);
    }
}

( ExtractImageLocations test testExtractLikeHelloWorldImprovedFromTopSecret)

для вашего PDF-файла, поэтому найдет изображение:

Processing page: 1
*******************************************************************
Found image [R8]
position in PDF = 39.0, 102.48 in user space units
raw image size  = 1209, 1640 in pixels
displayed size  = 516.3119, 700.3752 in user space units
displayed size  = 7.1709986, 9.727433 in inches at 72 dpi rendering
displayed size  = 182.14336, 247.0768 in millimeters at 72 dpi rendering

Осторожно,

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

...