如何修改pdf中的现有图层(可选内容组)?

如何修改pdf中的现有图层(可选内容组)?,pdf,pdfbox,layer,Pdf,Pdfbox,Layer,我正在实现允许用户以pdf格式绘制图形的功能。我想把所有的图形都画在一个图层上,用户可以看到也可以不看到。我可以在pdf中创建一个新图层。我也可以检索该层。但是,我不能对层pOptionalContentGroup进行修改。我尝试将PDOptionalContentGroup转换为PDPage,然后对PDPPage进行所需的更改。我还保存了PDDocument。它只创建了另一个与上一个同名的图层,但没有更改。下面是我使用的代码: PDFont font = PDType1Font.HELVETI

我正在实现允许用户以pdf格式绘制图形的功能。我想把所有的图形都画在一个图层上,用户可以看到也可以不看到。我可以在pdf中创建一个新图层。我也可以检索该层。但是,我不能对层pOptionalContentGroup进行修改。我尝试将PDOptionalContentGroup转换为PDPage,然后对PDPPage进行所需的更改。我还保存了PDDocument。它只创建了另一个与上一个同名的图层,但没有更改。下面是我使用的代码:

PDFont font = PDType1Font.HELVETICA;
PDDocument doc = PDDocument.load(src);
PDOptionalContentProperties ocprops = doc.getDocumentCatalog().getOCProperties();
foreach (string groupName in ocprops.getGroupNames())
{
    PDOptionalContentGroup group = ocprops.getGroup(groupName);
    COSBase cosbase = group.getCOSObject();
    PDPage groupPage = new PDPage((COSDictionary)cosbase);
    PDPageContentStream cs = new PDPageContentStream(doc, groupPage, true, false);
    cs.beginText();
    cs.setFont(font, 12);
    cs.moveTextPositionByAmount(150, 200);
    cs.drawString("Testing added to group:" + groupName);
    cs.endText();
    cs.close();
    doc.save(src);
}
OP在评论中表示,他只能使用1.8.x版本的PDFBox。因此,这里的代码是1.8'ish,针对PDFBox 1.8.12 for Java进行测试

在对您的问题的评论中,建议使用PDFBox类LayerUtibility作为自己解决方案的模板

因此,作为如何向现有OCG添加文本的示例,此基于LayerUtibility.AppendFormsLayer的帮助器方法显示了如何向现有或新OCG添加文本。它应该很简单,以适应添加的内容,你想添加

void addTextToLayer(PDDocument document, int pageNumber, String layerName, float x, float y, String text) throws IOException
{
    PDDocumentCatalog catalog = document.getDocumentCatalog();
    PDOptionalContentProperties ocprops = catalog.getOCProperties();
    if (ocprops == null)
    {
        ocprops = new PDOptionalContentProperties();
        catalog.setOCProperties(ocprops);
    }
    PDOptionalContentGroup layer = null;
    if (ocprops.hasGroup(layerName))
    {
        layer = ocprops.getGroup(layerName);
    }
    else
    {
        layer = new PDOptionalContentGroup(layerName);
        ocprops.addGroup(layer);
    }

    PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(pageNumber);

    PDResources resources = page.findResources();
    if (resources == null)
    {
        resources = new PDResources();
        page.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);

    PDFont font = PDType1Font.HELVETICA;

    PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true, true);
    contentStream.beginMarkedContentSequence(COSName.OC, resourceName);
    contentStream.beginText();
    contentStream.setFont(font, 12);
    contentStream.moveTextPositionByAmount(x, y);
    contentStream.drawString(text);
    contentStream.endText();
    contentStream.endMarkedContentSequence();

    contentStream.close();
}
试验方法TestAddContentOneworexistingCG


将文本添加到现有或尚未存在的OCG。

我将稍后再尝试。但作为第一个提示:将可选内容组字典视为一个页面是没有意义的,一个页面引用了它的所有内容,不管它可能属于哪个ocg。@mkl Tilman建议我使用pContentStream.beginMarkedContent。但是,我使用的是1.8版本的pdfbox。因此,我必须使用PDcontentstream.beginMarkedContentSequenceCOSName.OC,resourceName;,其中resource name是可选内容组的资源名称。但是,我无法获取OCG对应的资源名称。谢谢,它可以工作。我使用的唯一额外的一件事是检查OCG是否已经存在资源名称,然后我使用它来修改OCG。
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);

addTextToLayer(document, 0, "MyLayer", 30, 600, "Text in new layer 'MyLayer'");
addTextToLayer(document, 0, "MyOtherLayer", 230, 550, "Text in new layer 'MyOtherLayer'");
addTextToLayer(document, 0, "MyLayer", 30, 500, "Text in existing layer 'MyLayer'");
addTextToLayer(document, 0, "MyOtherLayer", 230, 450, "Text in existing layer 'MyOtherLayer'");

document.save(new File(RESULT_FOLDER, "TextInOCGs.pdf"));
document.close();