Изменение уровня масштабирования в контурах (закладках) в файлах PDF - PullRequest
0 голосов
/ 04 ноября 2019

Я бы хотел изменить уровень масштабирования в контурах, используя iText7. Обратите внимание, что это, вероятно, изменилось по сравнению с тем, как это было сделано в iText 5 .

Методом проб и ошибок я придумал код:

List<PdfOutline> outlines = pdfDoc.getOutlines(true).getAllChildren();

for (int i = 0; i < outlines.size(); i++) {

    PdfOutline outline = outlines.get(i);
    PdfDictionary content = outline.getContent();
    PdfDictionary pdfDictionary = (PdfDictionary) content.get(PdfName.A);
    if (pdfDictionary != null) {
        PdfArray arr = (PdfArray) pdfDictionary.get(PdfName.D);
        if (arr.size() == 5) { // for XYZ zoom type
            PdfName xyz = (PdfName) arr.get(1);
            arr.set(3, new PdfNumber(2_000));
            arr.set(4, new PdfNumber(2_000));
        }
    }  

РЕДАКТИРОВАТЬ

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

ОБНОВЛЕНИЕ Я пришел к другому решению (вдохновлен другим вопросом на SO ):

PdfNameTree destsTree = document.getCatalog().getNameTree(PdfName.Dests);
PdfOutline outline = document.getOutlines(false);
if (outline != null) {
    walkOutlines(outline, destsTree.getNames(), document);
}      

private static void walkOutlines(PdfOutline outline, Map<String, PdfObject> names,
            PdfDocument document) {

    if (outline.getDestination() != null) {

        int pageNumber = document.getPageNumber(
                (PdfDictionary) outline.getDestination().getDestinationPage(names));

        float height = document.getPage(pageNumber).getPageSize().getHeight();

        outline.setOpen(false);
        outline.addDestination(PdfExplicitRemoteGoToDestination.createXYZ(
                pageNumber, 0F, height, ZOOM_LEVEL));

    }
    for (PdfOutline child : outline.getAllChildren()) {
        walkOutlines(child, names, document);
    }
}

Ответы [ 2 ]

0 голосов
/ 14 ноября 2019

Ваш исходный код

Проблема в том, что приведенный выше код не работает, так как полученный PDF-файл сохраняется, но нет изменений в уровне масштабирования.

Пробуя исходный код, я не могу это подтвердить, уровень масштабирования и координата y (почему вы тоже это меняете?) Контура титульного листа изменены!

Другойконтуры не изменяются по двум причинам:

  • Ваш исходный код выполняет итерации только по контурам верхнего уровня (непосредственный каталог выделяет дочерние элементы), поэтому только записи контуров верхнего уровня можно изменить вообще.
  • В исходном коде предполагается, что у контуров есть действие GoTo ( A ), заключающее в явном виде XYZ Destination ( D сопоставление с 5-элементным массивом).

    Это в случае, если ваш документ верен только для титульного листа, все остальные схемы сразу содержат неявное имя с именем Назначение ( Dest mappiимя).

Ваш альтернативный код

Ваш альтернативный код действительно решает проблемы, в частности

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

В Adobe Readerкажется, что результат работает должным образом, но, глядя на него, можно увидеть, что есть проблемы:

  • Контур титульного листа (который был единственным из ваших контуров с Действие запись) теперь имеет и старую Action запись и новую Destination запись. Это строго говоря запрещено спецификацией;таким образом, вы должны удалить существующие записи Action .
  • Созданные массивы destination содержат целевую страницу (первую запись массива) в виде целочисленного номера страницы. Это разрешено только для пунктов назначения в Действия удаленного перехода . Поскольку ваши новые пункты назначения явно не Удаленные, а также Действия, это работает только потому, что Adobe Reader очень слабый. Вместо номера страницы вы должны использовать объект страницы, и вам не следует использовать PdfExplicitRemoteGoToDestination для начала.

Улучшение вашего альтернативного кода

Чтобы устранить вышеуказанные проблемы,измените

outline.addDestination(PdfExplicitRemoteGoToDestination.createXYZ(
        pageNumber, 0F, height, ZOOM_LEVEL));

на

outline.getContent().remove(PdfName.A);
outline.addDestination(PdfExplicitDestination.createXYZ(
        document.GetPage(pageNumber), 0F, height, ZOOM_LEVEL));

Строго говоря, ваш код может быть улучшен еще больше.

  • Вы используете PageSize, но для видимой области страницыВы должны использовать CropBox.
  • И использовать 0F, height в качестве координат верхнего левого угла целевого вида. При этом предполагается, что источником системы координат является левый нижний угол страницы. Вместо этого следует использовать box.getLeft(), box.getTop(), а box - поле обрезки рассматриваемой страницы.

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

0 голосов
/ 07 ноября 2019

Так как то так?

    PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(DEST));                                                   
    pdfDoc.getCatalog().setOpenAction(PdfExplicitDestination.createXYZ(pdfDoc.getPage(1), 0,                                                       pdfDoc.getPage(1).getPageSize().getHeight(), 0.75f)); 
    pdfDoc.close();

https://itextpdf.com/en/resources/faq/technical-support/itext-7/how-can-i-set-zoom-level-pdf-using-itext-7

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...