itext7 обновить текст аннотации

Я хотел бы обновить текстовое содержимое в аннотации FreeText, когда я копирую аннотацию из одного PDF-документа в другой, но по какой-то причине текст не обновляется в окончательном PDF-файле с использованием подхода, показанного ниже. Объект аннотации обновляется, но окончательный результат в PDF не отражает обновленное содержимое для типа аннотации FreeText. Как ни странно, аннотации типа Ink обновляются с учетом измененного содержимого, поскольку оно отображается в виде комментария в виде заметки, наложенного поверх самой аннотации Ink.

Вот небольшой фрагмент кода, который я использовал (при необходимости я могу добавить больше):

foreach (var anno in annots)
{
    var a = anno.GetPdfObject().CopyTo(masterPdfDoc);

    PdfAnnotation ano = PdfAnnotation.MakeAnnotation(a);
    var contents = ano.GetContents().ToString();
    ano.SetContents(new PdfString("COMMENT: " + contents));
    //ano.Put(PdfName.Contents, new PdfString("COMMENT: " + contents));

    masterDocPage.AddAnnotation(ano);
}

Был бы очень признателен за любой предоставленный совет. Спасибо


person James Cramer    schedule 27.08.2017    source источник
comment
Вы обновляете значение записи /Contents, но я не вижу, чтобы вы где-либо меняли внешний вид (/AP).   -  person Bruno Lowagie    schedule 27.08.2017
comment
Спасибо за быстрый ответ, Бруно! Приятно получить ответ от создателя :-) Я новичок в itext7 и спецификациях PDF в целом, поэтому я не понимаю, как внешний вид повлияет на текстовое содержимое, представленное в текстовой аннотации. Кажется, я просто могу обновить контент, и он отражается. Я просмотрел данные с помощью GetAppearanceDictionary () и GetAppearanceCharacteristics (), и я не могу понять, что мне нужно там изменить.   -  person James Cramer    schedule 27.08.2017
comment
@BrunoLowagie Я также нашел этот stackoverflow.com/questions/36902331 /, но ничего не заработало. Я попытался посмотреть на DA, N и т. Д., Но мне не очевидно, что я должен изменить. Я также попытался полностью удалить AP, как было предложено в отмеченном ответе через ano.Remove(PdfName.AP);.   -  person James Cramer    schedule 28.08.2017
comment
@InTheRed, при копировании материала и изменении необработанного содержимого аннотации эти изменения не переносятся автоматически. И поскольку визуальные эффекты диктует словарь внешнего вида, а не / Contents ... Многие высокоуровневые методы в iText фактически обновляют внешний вид (например, при заполнении формы), но вы используете манипуляции на низком уровне. Можно напрямую получить внешний вид и управлять им (через PdfAnnotation#getAppearanceDictionary()   -  person Samuel Huylebroeck    schedule 28.08.2017
comment
@SamuelHuylebroeck Вот данные словаря для аннотации выноски, в которой говорится «Добавить знак остановки». {[/ N, ‹* / BBox [1897.037 857.0107 2126.802 953.5811] / FormType 1 / Length 241 / Matrix [1 0 0 1 -1897.037 -857.0107] / Resources ‹› / Font ‹› / Helv 63 0 R Изменено; ›› / ProcSet [/ PDF / Text] ›› / Subtype / Form / Type / XObject ››]}   -  person James Cramer    schedule 28.08.2017
comment
@SamuelHuylebroeck Хорошо, я могу извлечь текст из потока появления, используя код, аналогичный показанному здесь: stackoverflow.com/questions/37014984/ Здесь показано, как извлечь текст, но как бы вы вставили или отредактировали текст? Нужно ли мне редактировать необработанные байты?   -  person James Cramer    schedule 28.08.2017
comment
Хорошо разобрался! Спасибо за вашу помощь. Этот пример также помог показать, как обновить байты объекта потока с помощью метода SetData (). developers.itextpdf.com/examples/stamping- content-existing-pdfs /   -  person James Cramer    schedule 29.08.2017


Ответы (1)


Следующий фрагмент кода копирует и изменяет текстовое содержимое аннотаций FreeText из 1 PDF-файла (т. Е. Аннотаций) и сохраняет измененные аннотации в новый PDF-файл. Хороший фрагмент кода похож на ответ этот пост, но был обновлен для iText7.

foreach (var anno in annots)
{
    var a = anno.GetPdfObject().CopyTo(masterPdfDoc);
    PdfAnnotation ano = PdfAnnotation.MakeAnnotation(a);

    var apDict = ano.GetAppearanceDictionary();
    if (apDict == null)
    {
        Console.WriteLine("No appearances.");
        continue;
    }
    foreach (PdfName key in apDict.KeySet())
    {
        Console.WriteLine("Appearance: {0}", key);
        PdfStream value = apDict.GetAsStream(key);
        if (value != null)
        {
            var text = ExtractAnnotationText(value);
            Console.WriteLine("Extracted Text: {0}", text);

            if (text != "")
            {
                var valueString = Encoding.ASCII.GetString(value.GetBytes());
                value.SetData(Encoding.ASCII.GetBytes(valueString.Replace(text, "COMMENT: " + text)));
            }
        }
    }
    masterDocPage.AddAnnotation(ano);
}

public static String ExtractAnnotationText(PdfStream xObject)
{
   PdfResources resources = new PdfResources(xObject.GetAsDictionary(PdfName.Resources));
   ITextExtractionStrategy strategy = new LocationTextExtractionStrategy();

   PdfCanvasProcessor processor = new PdfCanvasProcessor(strategy);
   processor.ProcessContent(xObject.GetBytes(), resources);
   var text = strategy.GetResultantText();
   return text;
}
person James Cramer    schedule 29.08.2017