Проследите весь PDF и измените некоторый атрибут с каким-либо объектом в нем, используя iText
Я работаю над программой-фильтром, которая превращает каждый черный текстовый блок в серый в файле PDF. Я прошел com.itextpdf.text.pdf.parser и не могу найти что-то подходящее для этой функции.
PS: я использую iTextSharp 5.5.10, для которого я не могу найти подходящий документ. Документы для iText5, кажется, работают в большинстве случаев, но есть разница. Есть ли документ для iTextSharp?
1 ответ
ОП уточнил свой вопрос в комментарии:
Мне интересно как написать парсер вроде
PdfTextExtractor
или что-то другое. Я исключал что-то вродеBaseParser
или около того, но ничего не нашел. Так что я соскучился по этому поводу.
Если вы ищете что-то вроде инфраструктуры редактирования, вы можете использовать PdfContentStreamEditor, представленный в этом ответе.
На основе PdfContentStreamEditor вы можете редактировать поток контента страниц PDF следующим образом:
PdfReader pdfReader = new PdfReader(resource);
PdfStamper pdfStamper = new PdfStamper(pdfReader, result);
PdfContentStreamEditor editor = new PdfContentStreamEditor()
{
@Override
protected void write(PdfContentStreamProcessor processor, PdfLiteral operator, List<PdfObject> operands) throws IOException
{
String operatorString = operator.toString();
if (TEXT_SHOWING_OPERATORS.contains(operatorString))
{
if (currentlyReplacedBlack == null)
{
BaseColor currentFillColor = gs().getFillColor();
if (BaseColor.BLACK.equals(currentFillColor))
{
currentlyReplacedBlack = currentFillColor;
super.write(processor, new PdfLiteral("rg"), Arrays.asList(new PdfNumber(0), new PdfNumber(1), new PdfNumber(0), new PdfLiteral("rg")));
}
}
}
else if (currentlyReplacedBlack != null)
{
if (currentlyReplacedBlack instanceof CMYKColor)
{
super.write(processor, new PdfLiteral("k"), Arrays.asList(new PdfNumber(0), new PdfNumber(0), new PdfNumber(0), new PdfNumber(1), new PdfLiteral("k")));
}
else if (currentlyReplacedBlack instanceof GrayColor)
{
super.write(processor, new PdfLiteral("g"), Arrays.asList(new PdfNumber(0), new PdfLiteral("g")));
}
else
{
super.write(processor, new PdfLiteral("rg"), Arrays.asList(new PdfNumber(0), new PdfNumber(0), new PdfNumber(0), new PdfLiteral("rg")));
}
currentlyReplacedBlack = null;
}
super.write(processor, operator, operands);
}
BaseColor currentlyReplacedBlack = null;
final List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ");
};
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++)
{
editor.editPage(pdfStamper, i);
}
pdfStamper.close();
( ChangeTextColor.java test testChangeBlackTextToGreenDocument
)
В PdfContentStreamEditor метод write
вызывается для каждой инструкции в потоке контента и записывает ее обратно. Переопределяя этот метод и передавая частично разные инструкции суперклассу write
можно редактировать поток.
Эта реализация показывает, как изменить цвет текста данного цвета. В этом случае черный текст меняется на зеленый.
Осторожно, это всего лишь подтверждение концепции, а не окончательное и полное решение. Особенно
- Текст считается черным, если для его
color
выражениеBaseColor.BLACK.equals(color)
являетсяtrue
; как равенство междуBaseColor
и его классы-потомки не полностью определены, это может привести к ложным срабатываниям. PdfContentStreamEditor
только проверяет и редактирует поток контента самой страницы, а не потоки контента отображаемых форм или шаблонов; таким образом, некоторый текст может быть не найден.
Совершенствование класса для правильного определения черного цвета, а также для рекурсивного обхода и редактирования потоков содержимого используемых шаблонов и xobjects остается в качестве упражнения для читателя.
Используйте этот подход, чтобы изменить цвет. Я использую приведенный ниже код для изменения цвета гиперссылок.
PdfCanvasEditor editor = new PdfCanvasEditor() {
@Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (SET_FILL_RGB.equals(operatorString) && operands.size() == 4) {
if (isApproximatelyEqual(operands.get(0), 0) &&
isApproximatelyEqual(operands.get(1), 0) &&
isApproximatelyEqual(operands.get(2), 1)) {
super.write(processor, new PdfLiteral("g"), Arrays.asList(new PdfNumber(0), new PdfLiteral("g")));
return;
}
}
if (SET_STROKE_RGB.equals(operatorString) && operands.size() == 4) {
if (isApproximatelyEqual(operands.get(0), 0) &&
isApproximatelyEqual(operands.get(1), 0) &&
isApproximatelyEqual(operands.get(2), 1)) {
super.write(processor, new PdfLiteral("G"), Arrays.asList(new PdfNumber(0), new PdfLiteral("G")));
return;
}
}
super.write(processor, operator, operands);
}
boolean isApproximatelyEqual(PdfObject number, float reference) {
return number instanceof PdfNumber && Math.abs(reference - ((PdfNumber)number).floatValue()) < 0.01f;
}
final String SET_FILL_RGB = "rg";
final String SET_STROKE_RGB = "RG";
};
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {
editor.editPage(pdfDocument, i);
}
}