Как добавить текст к изображению?
В моем проекте я использую iText для создания PDF-документа.
Предположим, что высота страницы составляет 500pt (1 единица пользователя = 1 балл) и что я пишу текст на страницу, а затем изображение.
Если содержание и изображение требуют менее 450pt, текст предшествует изображению. Если содержимое и изображение превышают 450pt, текст пересылается на следующую страницу.
- Роль / цель ContextLoaderListener весной?
- Spring Boot и несколько внешних файлов конфигурации
- Spring 3.0 делает ответ JSON с помощью конвертера сообщений Jackson
- Весной MVC
- Spring 3 RequestMapping: Получить значение пути
Мой вопрос: как я могу получить оставшееся свободное пространство перед написанием изображения?
- Перенаправление весной MVC
- Определение пространств имен Spring JAXB без использования NamespacePrefixMapper
- Многостраничный запрос Spring MVC с JSON
- Весенний classификатор и заполнитель свойств
- Spring - вставка зависимости в ServletContextListener
- Spring REST Service: как настроить удаление нулевых объектов в json-ответе
- Как вручную принудительно совершить фиксацию в методе @Transactional?
- REST API - DTO или нет?
Прежде всего: при добавлении текста и изображений на страницу iText иногда меняет порядок текстового контента и изображения. Вы можете избежать этого, используя:
writer.setStrictImageSequence(true);
Если вы хотите узнать текущую позицию «курсора», вы можете использовать метод getVerticalPosition()
. К сожалению, этот метод не очень изящный: для него требуется булевский параметр, который добавит новую строку (если это true
) или даст вам позицию в текущей строке (если false
).
Я не понимаю, почему вы хотите получить вертикальное положение. Это потому, что вы хотите иметь заголовок, сопровождаемый изображением, и хотите, чтобы надпись и изображение находились на одной странице?
В этом случае вы можете поместить свой текст и изображения внутри ячейки таблицы и проинструктировать iText не разделять строки. В этом случае iText будет пересылать как текст, так и изображение в правильном порядке на следующую страницу, если содержимое не соответствует текущей странице.
Обновить:
Исходя из дополнительной информации, добавленной в комментариях, теперь ясно, что OP хочет добавить изображения с водяными знаками.
Существует два подхода к достижению этого, в зависимости от фактического требования.
Подход 1:
Первый подход объясняется в примере WatermarkedImages1 . В этом примере мы создаем PdfTemplate
к которому мы добавляем изображение, а также некоторый текст, написанный поверх этого изображения. Затем мы можем обернуть этот PdfTemplate
внутри изображения и добавить это изображение вместе с его водяным знаком с помощью одного document.add()
.
Это метод, который выполняет всю магию:
public Image getWatermarkedImage(PdfContentByte cb, Image img, String watermark) throws DocumentException { float width = img.getScaledWidth(); float height = img.getScaledHeight(); PdfTemplate template = cb.createTemplate(width, height); template.addImage(img, width, 0, 0, height, 0, 0); ColumnText.showTextAligned(template, Element.ALIGN_CENTER, new Phrase(watermark, FONT), width / 2, height / 2, 30); return Image.getInstance(template); }
Вот как мы добавляем изображения:
PdfContentByte cb = writer.getDirectContentUnder(); document.add(getWatermarkedImage(cb, Image.getInstance(IMAGE1), "Bruno")); document.add(getWatermarkedImage(cb, Image.getInstance(IMAGE2), "Dog")); document.add(getWatermarkedImage(cb, Image.getInstance(IMAGE3), "Fox")); Image img = Image.getInstance(IMAGE4); img.scaleToFit(400, 700); document.add(getWatermarkedImage(cb, img, "Bruno and Ingeborg"));
Как вы можете видеть, у нас есть очень большое изображение (картина моей жены и меня). Нам нужно масштабировать это изображение так, чтобы оно соответствовало странице. Если вы хотите этого избежать, взгляните на второй подход.
Подход 2:
Второй подход объясняется в примере WatermarkedImages2 . В этом случае мы добавляем каждое изображение в PdfPCell
. Этот PdfPCell
масштабирует изображение так, чтобы оно соответствовало ширине страницы. Чтобы добавить водяной знак, мы используем событие ячейки:
class WatermarkedCell implements PdfPCellEvent { String watermark; public WatermarkedCell(String watermark) { this.watermark = watermark; } public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) { PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS]; ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, new Phrase(watermark, FONT), (position.getLeft() + position.getRight()) / 2, (position.getBottom() + position.getTop()) / 2, 30); } }
Это событие ячейки можно использовать следующим образом:
PdfPCell cell; cell = new PdfPCell(Image.getInstance(IMAGE1), true); cell.setCellEvent(new WatermarkedCell("Bruno")); table.addCell(cell); cell = new PdfPCell(Image.getInstance(IMAGE2), true); cell.setCellEvent(new WatermarkedCell("Dog")); table.addCell(cell); cell = new PdfPCell(Image.getInstance(IMAGE3), true); cell.setCellEvent(new WatermarkedCell("Fox")); table.addCell(cell); cell = new PdfPCell(Image.getInstance(IMAGE4), true); cell.setCellEvent(new WatermarkedCell("Bruno and Ingeborg")); table.addCell(cell);
Вы будете использовать этот подход, если все изображения имеют более или менее одинаковый размер, и если вы не хотите беспокоиться об установке изображений на странице.
Рассмотрение:
Очевидно, что оба подхода имеют другой результат из-за выбора дизайна. Пожалуйста, сравните полученные PDF-файлы, чтобы увидеть разницу: watermark_template.pdf и watermark_table.pdf