Editing layers in Adobe Illustrator PDF-s using PDFNet SDK.

Q: I've a file created with Illustrator with two layers. And I want to
use PDFTron to add new layer to it. I've used the attached code which
is modified from one the examples. The new layer is successfully
added, and viewed by Adobe Reader. When I reopen the file Illustrator,
the newly added Layer isn't shown, Why ??

import pdftron.Common.Matrix2D;
import pdftron.Common.PDFNetException;
import pdftron.PDF.*;
import pdftron.PDF.OCG.*;
import pdftron.SDF.*;

// This sample demonstrates how to create layers in PDF.
// The sample also shows how to extract and render PDF layers in
// that contain optional content groups (OCGs)
// With the introduction of PDF version 1.5 came the concept of
// Layers, or as they are more formally known Optional Content Groups
// refer to sections of content in a PDF document that can be
// viewed or hidden by document authors or consumers. This capability
is useful
// in CAD drawings, layered artwork, maps, multi-language documents
// Couple of notes regarding this sample:
// ---------------------------------------
// - This sample is using CreateLayer() utility method to create new
// CreateLayer() is relatively basic, however it can be extended to
// other optional entries in the 'OCG' and 'OCProperties'
dictionary. For
// a complete listing of possible entries in OC dictionary please
refer to
// section 4.10 'Optional Content' in the PDF Reference Manual.
// - The sample is grouping all layer content into separate Form
// Although using PDFNet is is also possible to specify Optional
Content in
// Content Streams (Section 4.10.2 in PDF Reference), Optional
Content in
// XObjects results in PDFs that are cleaner, less-error prone, and
// to process.
public class PDFLayersTest
  // Relative path to the folder containing test files.
  static String input_path = "/home/mostafa/Desktop/PDFNetC/PDFNetC/
  static String output_path = "out/";

  public static void main(String[] args)

      PDFDoc doc=new PDFDoc("template4.pdf");

      // Create layer...
      Group image_layer = createLayer(doc, "Image Layer");

      // Start a new page ------------------------------------
      Page page = doc.getPage(1); // Get the first page in the document.

      ElementBuilder builder = new ElementBuilder(); // ElementBuilder is
used to build new Element objects
      ElementWriter writer = new ElementWriter(); // ElementWriter is
used to write Elements to the page
      writer.begin(page, true); // Begin writing to the page

      // Add new content to the page and associate it with one of the
      Element element = builder.createForm(createGroup1(doc,

      writer.end(); // save changes to the current page
      // doc.pagePushBack(page);

      // Set the default viewing preference to display 'Layer' tab.
      PDFDocViewPrefs prefs = doc.getViewPrefs();

      doc.save((output_path + "pdf_layers.pdf"), SDFDoc.e_linearized,
    catch(Exception e)


  // A utility function used to add new Content Groups (Layers) to the
  static Group createLayer(PDFDoc doc, String layer_name) throws
    Group grp = Group.create(doc, layer_name);
    Config cfg = doc.getOCGConfig();
    if (cfg == null)
      cfg = Config.create(doc, true);

    // Add the new OCG to the list of layers that should appear in PDF
viewer GUI.
    Obj layer_order_array = cfg.getOrder();
    if (layer_order_array == null)
      layer_order_array = doc.createIndirectArray();
    layer_order_array.insert(2, grp.getSDFObj());


    return grp;

  // Creates some content (3 images) and associate them with the image
  static Obj createGroup1(PDFDoc doc, Obj layer) throws PDFNetException
    ElementWriter writer = new ElementWriter();

    // Create an Image that can be reused in the document or on the same
    Image img = Image.create(doc.getSDFDoc(), "/home/mostafa/Desktop/

    ElementBuilder builder = new ElementBuilder();
    Element element = builder.createImage(img, new Matrix2D
(img.getImageWidth()/2, -145, 20, img.getImageHeight()/2, 200, 150));
    GState gstate = element.getGState(); // use the same image (just
change its matrix)
    gstate.setTransform(250, 0, 0, 333, 414, 226);

    Obj grp_obj = writer.end();

    // Indicate that this form (content group) belongs to the given
layer (OCG).
    grp_obj.put("OC", layer);
    grp_obj.putRect("BBox", 0, 0, 1000, 1000); // Set the clip box for
the content.

    return grp_obj;
A: The problem is that PDF layers (OCG-s) are different from
Illustrator layers and Illustrator input filer does not map them 1-1.
Illustrator could 'export PDF' layers during file save, however these
layers are different from its own representation. In order to allow
roundtrip, Illustrator stores its private data under 'PieceInfo/
Illustrator/Private' in the page dictionary. To inspect this data you
can use CosEdit (http://www.pdftron.com/cosedit/index.html - in the
address location paste 'trailer/Root/Pages/Kids/0/PieceInfo/
Illustrator/Private'). Older versions of Illustrator were using marked
content to add extra structuring/layering information (instead of
PieceInfo blob). You can use PDFNet to extract & edit private
Illustrator data, however parsing and editing this data is probably
not fun.