Можно ли использовать PDFNet SDK для удаления невидимых слоев PDF (OCG), включая контент?

Я новичок в PDFNet SDK и все еще пытаюсь понять, как работают некоторые функции PDF. Я впечатлен широтой и глубиной SDK, но я пытаюсь понять, как SDK работает со слоями (также известными как группы дополнительного контента или OCG). В частности, я пытаюсь определить, как можно определить, какие слои невидимы (OFF), чтобы их и их содержимое можно было удалить из PDF. Сначала я сосредоточился на классах в пространстве имен pdftron.PDF.OCG, особенно на классе Group. Это позволяет мне повторять группы и получать основную информацию, такую ​​как имя и текущее состояние (ВКЛ/ВЫКЛ), как показано в фрагменте кода ниже:

Config init_cfg = doc.GetOCGConfig(); 
Context ctx = new Context(init_cfg); 


Obj ocgs = doc.GetOCGs(); // Get the array of all OCGs in the document. 
if (ocgs != null) 
{ 
    int i, sz = ocgs.Size(); 
    for (i = 0; i < sz; ++i) 
    { 
        Group ocg = new Group(ocgs.GetAt(i)); 
        bool ocgState = ocg.GetCurrentState(ctx);  // check if ocg is OFF or ON 
        if (!ocgState) // layer is not visible
        {
            // need calls here to delete layer and content
        }
    } 
} 

Все идет нормально. Однако я не вижу способа удалить слои и связанный с ними контент внутри этих классов. Я что-то пропустил? Если нет, есть ли в SDK другой способ удалить слои?

Заранее спасибо!


person smleino    schedule 17.08.2015    source источник


Ответы (1)


Итак, после значительного изучения образцов SDK и долгих экспериментов я нашел один подход, который до сих пор работает с PDF-файлами, которые я пробовал. Решение основано на образце ElementEdit в сочетании с методами Context.SetNonOCDrawing(), Context.SetOCDrawMode() и Element.IsOCVisible() для пропуска элементов страницы, которые не видны, в зависимости от состояния слоя ON/OFF. . Конечным результатом является удаление контента для отключенных слоев, при этом сам слой все еще остается позади, но теперь он пуст. Не идеально, но для моих целей достаточно. Во всяком случае, вот код, который я придумал на основе примера SDK:

    private void ProcessElements(ElementReader reader, ElementWriter writer, XSet visited)
    {
        Element element;
        while ((element = reader.Next()) != null)   // Read page contents
        {

            switch (element.GetType())
            {
                //always write these element types (visible or non-visible)
                case Element.Type.e_marked_content_begin:
                case Element.Type.e_marked_content_end:
                case Element.Type.e_marked_content_point:
                case Element.Type.e_group_begin:
                case Element.Type.e_group_end:
                    writer.WriteElement(element);
                    continue;
            }

            // do not retain other elements that are not visible
            if (!element.IsOCVisible())
                continue;

            // retain remaining element types if visible
            switch (element.GetType())
            {

                // special processing for form elements
                case Element.Type.e_form:
                    {
                        writer.WriteElement(element); // write Form XObject reference to current stream

                        Obj form_obj = element.GetXObject();
                        if (!visited.Contains(form_obj.GetObjNum())) // if this XObject has not been processed
                        {
                            // recursively process the Form XObject
                            visited.Add(form_obj.GetObjNum());
                            ElementWriter new_writer = new ElementWriter();

                            reader.FormBegin();
                            new_writer.Begin(form_obj, true);
                            ProcessElements(reader, new_writer, visited);
                            new_writer.End();
                            reader.End();
                        }
                        break;
                    }

                default:
                    writer.WriteElement(element);
                    break;
            }
        }
    }


    private void RemoveNonVisibleLayers_Click(string filename, string outputfile)
    {

        PDFNet.Initialize();

        try
        {

            // Open the test file
            XSet visited = new XSet();

            using (PDFDoc doc = new PDFDoc(filename))
            using (ElementReader page_reader = new ElementReader())
            using (ElementWriter writer = new ElementWriter())
            {
                doc.InitSecurityHandler();
                Config init_cfg = doc.GetOCGConfig();
                Context ctx = new Context(init_cfg);

                ctx.SetNonOCDrawing(false);
                ctx.SetOCDrawMode(Context.OCDrawMode.e_VisibleOC);

                PageIterator itr;
                for (itr = doc.GetPageIterator(); itr.HasNext(); itr.Next())        //  Read every page
                {
                    itr.GetPageNumber());

                    page_reader.Begin(itr.Current(), ctx);
                    writer.Begin(itr.Current(), ElementWriter.WriteMode.e_replacement, false);

                    ProcessElements(page_reader, writer, visited);
                    writer.End();
                    page_reader.End();
                }

                doc.Save(outputfile, SDFDoc.SaveOptions.e_remove_unused);
                doc.Close();
            }
        }
        catch (PDFNetException ee)
        {
            Console.WriteLine(ee.Message);
        }

    }
person smleino    schedule 18.08.2015