Копирование аннотаций с помощью PdfWriter вместо PdfCopy - PullRequest
0 голосов
/ 26 октября 2018

Мне нужно скопировать аннотации, используя PdfWriter вместо PdfCopy, потому что во время копирования мне нужно изменить размер / повернуть страницу. Может кто-нибудь сказать мне, как это сделать?

1 Ответ

0 голосов
/ 31 октября 2018

Вы думаете, что вам нужно использовать простой PdfWriter вместо PdfCopy для копирования PDF, потому что вам необходимо изменить размер / повернуть страницу и iText в действии, 2-е издание, говорит это невозможно с классом PdfCopy. Таким образом, вы ищете способ скопировать аннотации в таком контексте.

Вместо этого вам нужно искать способ поворота или изменения размера страниц и одновременно использовать PdfCopy, тем не менее!

Хотя верно, что PdfCopy класс сам по себе не позволяет изменять размер или поворачивать страницы, вы можете манипулировать PDF-файлом, загруженным в PdfReader, а также изменять его размер и / или поворачивать его страницы до с использованием класса PdfCopy. Если вы затем скопируете страницы из этого манипулированного PdfReader в PdfCopy, вы получите результат с измененными или повернутыми страницами (из-за манипулированного PdfReader) и всеми присутствующими аннотациями (из-за использования * 1025) *).

например. Вы можете изменить размер всех страниц в PdfReader следующим образом:

void resize(PdfReader pdfReader, float width, float height) {
    for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
        boolean switched = pdfReader.getPageRotation(i) % 180 != 0;
        float widthHere = switched ? height : width;
        float heightHere = switched ? width : height;

        Rectangle cropBox = pdfReader.getCropBox(i);
        float halfWidthGain = (widthHere - cropBox.getWidth()) / 2;
        float halfHeightGain = (heightHere - cropBox.getHeight()) / 2;
        Rectangle newCropBox = new Rectangle(cropBox.getLeft() - halfWidthGain, cropBox.getBottom() - halfHeightGain,
                cropBox.getRight() + halfWidthGain, cropBox.getTop() + halfHeightGain);

        Rectangle mediaBox = pdfReader.getPageSize(i);
        Rectangle newMediaBox = new Rectangle(Math.min(newCropBox.getLeft(), mediaBox.getLeft()),
                Math.min(newCropBox.getBottom(), mediaBox.getBottom()),
                Math.max(newCropBox.getRight(), mediaBox.getRight()),
                Math.max(newCropBox.getTop(), mediaBox.getTop()));

        PdfDictionary pageDictionary = pdfReader.getPageN(i);
        pageDictionary.put(PdfName.MEDIABOX, new PdfArray(new float[] {newMediaBox.getLeft(), newMediaBox.getBottom(),
                newMediaBox.getRight(), newMediaBox.getTop()}));
        pageDictionary.put(PdfName.CROPBOX, new PdfArray(new float[] {newCropBox.getLeft(), newCropBox.getBottom(),
                newCropBox.getRight(), newCropBox.getTop()}));
    }
}

( CopyWithResizeRotate вспомогательный метод)

и вы можете повернуть все страницы в PdfReader следующим образом:

void rotate(PdfReader pdfReader) {
    for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
        int rotation = pdfReader.getPageRotation(i);
        int newRotation = rotation + 90 % 360;

        PdfDictionary pageDictionary = pdfReader.getPageN(i);
        if (newRotation == 0)
            pageDictionary.remove(PdfName.ROTATE);
        else
            pageDictionary.put(PdfName.ROTATE, new PdfNumber(newRotation));
    }
}

( CopyWithResizeRotate вспомогательный метод)

Используя эти помощники, вы можете, например, создайте PDF-файл из повернутых и / или измененных по размеру страниц исходного PDF-файла и скопируйте их следующим образом:

byte[] wildPdf = RETRIEVE_SOURCE_PDF;

PdfReader pdfReaderOriginal = new PdfReader(wildPdf);
PdfReader pdfReaderRotate = new PdfReader(wildPdf);
rotate(pdfReaderRotate);
PdfReader pdfReaderResize = new PdfReader(wildPdf);
resize(pdfReaderResize, PageSize.LETTER.getWidth(), PageSize.LETTER.getHeight());
PdfReader pdfReaderRotateResize = new PdfReader(wildPdf);
rotate(pdfReaderRotateResize);
resize(pdfReaderRotateResize, PageSize.LETTER.getWidth(), PageSize.LETTER.getHeight());

try (   OutputStream os = new FileOutputStream(new File(RESULT_FOLDER, "wild-rotated-resized.pdf"))) {
    Document document = new Document();
    PdfCopy pdfCopy = new PdfCopy(document, os);
    document.open();
    pdfCopy.addDocument(pdfReaderOriginal);
    pdfCopy.addDocument(pdfReaderRotate);
    pdfCopy.addDocument(pdfReaderResize);
    pdfCopy.addDocument(pdfReaderRotateResize);
    document.close();
}

( CopyWithResizeRotate метод тестирования testRotateResizeAndCopy)

Результат может выглядеть следующим образом: первая строка оригинальных страниц (# 1 A4, # 2 HALFLETTER, # 3 A5, # 4 A5 повернута, # 5 500x700), вторая строка повернута, третья строка - измененные размеры (до буквы), а четвертый ряд повернутые и измененные размеры (до буквы). К сожалению, эскизы Adobe Reader не масштабируются:

screen shot

Работа только с одним PDF

Если вы на самом деле хотите изменять размеры / поворачивать страницы только одного входного PDF, вам не следует использовать экземпляр PdfCopy, а вместо этого PdfStamper:

PdfReader pdfReader = new PdfReader(SOURCE);
[...manipulate properties of the pdfReader like above...]
new PdfStamper(pdfReader, TARGET_STREAM).close();

Преимущество здесь в том, что сохраняются не только данные уровня страницы, но и данные уровня документа исходного документа.

Специальные аннотации

Существует один тип аннотаций, который будет вести себя неожиданно с кодом выше: аннотации с установленным флагом NoRotate . Такие аннотации будут вести себя так, когда их главная страница вращается:

screenshot from specification

(ISO 32000-2 раздел 12.5.3 - Флажки аннотации)

...