Вы думаете, что вам нужно использовать простой 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 не масштабируются:
Работа только с одним PDF
Если вы на самом деле хотите изменять размеры / поворачивать страницы только одного входного PDF, вам не следует использовать экземпляр PdfCopy
, а вместо этого PdfStamper
:
PdfReader pdfReader = new PdfReader(SOURCE);
[...manipulate properties of the pdfReader like above...]
new PdfStamper(pdfReader, TARGET_STREAM).close();
Преимущество здесь в том, что сохраняются не только данные уровня страницы, но и данные уровня документа исходного документа.
Специальные аннотации
Существует один тип аннотаций, который будет вести себя неожиданно с кодом выше: аннотации с установленным флагом NoRotate . Такие аннотации будут вести себя так, когда их главная страница вращается:
(ISO 32000-2 раздел 12.5.3 - Флажки аннотации)