Как создать многослойный PDF-файл с помощью PdfBox?

1

У меня возникла проблема с созданием многослойной pdf-страницы с использованием PdfBox. Я видел несколько сообщений здесь по этому вопросу, но они сосредоточены на импорте страниц из другого PDF в целевой документ.

Мое дело - бит-лит, отличный от другого (по крайней мере, я так думаю :)). Я создал класс MapImage, который содержит размер бумаги (в пикселях) и список BufferedImages, который я хочу добавить к одной странице PDF.

Вот код, который я пробовал:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
PDDocument document = new PDDocument();
for (MapImage image : images) {
    PDPage page = new PDPage(new PDRectangle(image.getPaperWidth(), image.getPaperHeight()));
    page.setResources(new PDResources(new COSDictionary()));
    document.addPage(page);

    LayerUtility layerUtility = new LayerUtility(document);
    int i=1;
    for(BufferedImage layer : image.getLayers()) {
        PDJpeg img = new PDJpeg(document, layer);                        
        layerUtility.appendFormAsLayer(page, new PDXObjectForm(img.getCOSStream()), new AffineTransform(), "Layer " + i++);
    }
}
document.save(baos);
document.close();

К сожалению, полученный PDF файл поврежден. Мне удалось создать страницу с одним изображением (без слоев), но, к сожалению, я понятия не имею, как это сделать.

Кто-нибудь столкнулся с такой проблемой?

  • 0
    Есть ли причина, по которой вы хотите использовать дополнительные группы контента (иначе слои) вообще?
  • 0
    Да. Я должен был подготовить PDF-файл, который содержит данные карты. Карта состоит из множества разных слоев. Иногда человеку, получающему PDF, необходимо отключить некоторые слои, чтобы увидеть, что находится под ними.
Показать ещё 1 комментарий
Теги:
pdf
pdfbox
layer

1 ответ

2
Лучший ответ

Хорошо, я решил. Это метод, который делает то, что я хотел. Может быть, это будет полезно для кого-то :)

public static PDOptionalContentGroup appendImageAsLayer(PDDocument document, PDPage targetPage, BufferedImage image, String layerName) throws IOException {
    PDDocumentCatalog catalog = document.getDocumentCatalog();
    PDOptionalContentProperties ocprops = catalog.getOCProperties();
    if (ocprops == null) {
        ocprops = new PDOptionalContentProperties();
        catalog.setOCProperties(ocprops);
    }
    if (ocprops.hasGroup(layerName)) {
        throw new IllegalArgumentException("Optional group (layer) already exists: " + layerName);
    }

    PDOptionalContentGroup layer = new PDOptionalContentGroup(layerName);
    ocprops.addGroup(layer);

    PDResources resources = targetPage.findResources();
    if(resources == null ) {
        resources = new PDResources(new COSDictionary());
        targetPage.setResources(resources);
    }
    PDPropertyList props = resources.getProperties();
    if (props == null) {
        props = new PDPropertyList();
        resources.setProperties(props);
    }

    // Find first free resource name with the pattern "MC<index>"
    int index = 0;
    PDOptionalContentGroup ocg;
    COSName resourceName;
    do {
        resourceName = COSName.getPDFName("MC" + index);
        ocg = props.getOptionalContentGroup(resourceName);
        index++;
    } while (ocg != null);
    // Put mapping for our new layer/OCG
    props.putMapping(resourceName, layer);
    PDJpeg img = new PDJpeg(document, image);

    PDPageContentStream contentStream = new PDPageContentStream(document, targetPage, true, false);
    contentStream.beginMarkedContentSequence(COSName.OC, resourceName);
    contentStream.drawImage(img, 0, 0);
    contentStream.endMarkedContentSequence();
    contentStream.close();

    return layer;
}
  • 0
    что означает «MC» + индекс?
  • 0
    Честно говоря - понятия не имею. Я придумал это решение, используя кусочки кода, которые я нашел в сети. Я предполагаю, что это своего рода соглашение об именах ресурсов, которое распознается зрителями PDF. Я не эксперт в формате pdf и, к сожалению, у меня не было времени, чтобы глубже изучить это. Но я также хотел бы услышать ответ на ваш вопрос.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню