Как определить строку подписи в документе PDF и затем вставить подпись?
На прошлой неделе меня попросили создать приложение для слепого, чтобы программно заполнить PDF-документ. Проблема, с которой он сталкивается, заключается в том, что если поля в документе не помечены правильно, он не сможет поместить свою подпись и другую информацию в документ в нужном месте.
Мой первый подход состоял в том, чтобы попытаться прочитать документ с помощью iTextSharp, а затем вставить его подпись в поле, которое, скорее всего, будет полем для подписи:
public string[] MassFieldEdit(IDictionary<string, string> userData, string originalDocument, string edittedDocument, bool flatten)
{
PdfReader reader = new PdfReader(originalDocument);
reader.SelectPages("1-" + reader.NumberOfPages.ToString());
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(edittedDocument, FileMode.Create)))
{
AcroFields form = stamper.AcroFields;
ICollection<string> fieldKeys = form.Fields.Keys;
List<string> leftover = new List<string>(fieldKeys);
foreach (string fieldKey in fieldKeys)
{
foreach (KeyValuePair<string, string> s in user)
{
//Replace Form field with my custom data
if (fieldKey.ToLower().Contains(s.Key.ToLower()))
{
form.SetField(fieldKey, s.Value);
leftover.Remove(fieldKey);
}
}
}
//The below will make sure the fields are not editable in
//the output PDF.
stamper.FormFlattening = flatten;
return leftover.ToArray();
}
}
Это работает, беря набор словаря, ключом является слово или фраза, проверяя его по полям PDF, а затем вставляя значение в поля, если поле соответствует слову или фразе в ключе.
Поле для подписи до того, как моя программа отредактирует его.
Но проблема, с которой я столкнулся сейчас, заключается в том, что если поле не существует, то хотя оно может иметь "знак здесь" рядом с пунктирной линией, невозможно вставить текст в пунктирную линию, не зная точно, где находится эта пунктирная линия, и не может Мой пользователь выбирает пунктирную линию, потому что это побеждает точку программы.
Я посмотрел на ряд предыдущих вопросов и ответов, в том числе:
- Как получить TextField из AcroFields с помощью iText/Sharp?
- Как конвертировать PDF в WORD в C#
- Вставьте текст в существующий PDF с помощью itextsharp
- ITextSharp вставить текст в существующий PDF
Честно говоря, я застрял, я впервые работаю с PDF документами. Мне нужен способ обнаружить строку подписи, а затем вставить его имя в строку подписи с большей уверенностью, чем делать точечные выстрелы по именам полей. Как в ситуациях, когда существует правильно помеченное поле, так и в ситуациях, когда строка подписи может быть не более чем строкой текста с надписью "подпишите здесь".
Буду очень признателен за любую помощь, даже частичные решения и толчки в правильном направлении.
1 ответ
Надежное решение (так называемое "решение для тяжелой работы")
- Реализуйте IEventListener (класс iText7)
- Используйте IEventListener для получения уведомлений об инструкциях рендеринга текста и операциях рисования линий
- Инструкции рендеринга не всегда отображаются в логическом (читаемом) порядке. Исправьте это путем реализации компаратора для этих объектов
- Сортировать по компаратору
- Используйте определение языка для определения языка (n-граммный подход прост, но должен быть достаточным)
- Словарная атака. Ищите все вхождения слов, которые означают "подписать здесь" на любом языке, на котором написан документ (отсюда шаг 5)
- В случае нескольких кандидатов или их отсутствия используйте команды рендеринга строк, чтобы найти вероятного кандидата из печально известной "пунктирной линии"
Этот подход не прост, но существует много исследований по распознаванию структурных элементов в PDF-файлах. В частности, если вы запустите поиск в Google, вы найдете множество полезных статей, в которых люди пытались обнаружить таблицы, списки, абзацы и т. Д.