如引用问题上下文中的评论所述
通过将填充或描边指令替换为删除当前路径而不绘制它的指令,可以很容易地使上面的编辑器类删除矢量图形。如果仅在适用的当前颜色为蓝色的情况下这样做,那么在您的示例 PDF 的情况下可能会完成这项工作。但请注意,在带有其他带有蓝色元素(例如徽标)的图形的文档中,这些也会被破坏。
这是以下内容编辑器的作用:
class PdfGraphicsRemoverByColor extends PdfCanvasEditor {
public PdfGraphicsRemoverByColor(Color color) {
this.color = color;
}
@Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (color.equals(getGraphicsState().getFillColor())) {
switch (operatorString) {
case "f":
case "f*":
case "F":
operatorString = "n";
break;
case "b":
case "b*":
operatorString = "s";
break;
case "B":
case "B*":
operatorString = "S";
break;
}
}
if (color.equals(getGraphicsState().getStrokeColor())) {
switch (operatorString) {
case "s":
case "S":
operatorString = "n";
break;
case "b":
case "B":
operatorString = "f";
break;
case "b*":
case "B*":
operatorString = "f*";
break;
}
}
operator = new PdfLiteral(operatorString);
operands.set(operands.size() - 1, operator);
super.write(processor, operator, operands);
}
final Color color;
}
(RemoveGraphicsByColor 助手类)
这样应用:
try ( PdfReader pdfReader = new PdfReader(INPUT);
PdfWriter pdfWriter = new PdfWriter(OUTPUT);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new PdfGraphicsRemoverByColor(ColorConstants.BLUE);
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++)
{
editor.editPage(pdfDocument, i);
}
}
(RemoveGraphicsByColor 测试)
到引用问题中的示例文件Control_of_nitrosamine_impurities_in_sartans__rev.pdf、EDQM_reports_issues_of_non-compliance_with_tooth__Mac.pdf 和originalFile.pdf,得到:
和
和
请注意,这只是概念验证,而不是最终和完整的解决方案。特别是:
-
仅考虑 RGB 蓝色。这可能是一个问题,尤其是在明确设计用于打印的文档(可能使用 CMYK 颜色)的情况下。
-
只要是蓝色的,所有路径填充和描边都会被丢弃。根据您的文档,这可能需要过滤。
-
PdfCanvasEditor只检查和编辑页面本身的内容流,而不是显示的表单XObjects或patterns的内容流;因此,可能找不到某些内容。它可以很容易地概括。
与其他 RGB 色彩空间不同的蓝色深浅
测试上面的代码,您发现文档中的蓝线没有被删除。事实证明,这些蓝色不是来自 DeviceRGB 标准 RGB,而是来自 ICCBased 颜色空间,更准确地说是配置 RGB 颜色空间。此外,在一个文档中,使用的不是纯蓝色 0 0 1,而是 .17255 .3098 .63529 蓝色。
为了也能够处理这些文件,上述方法必须是通用的;例如我们可以使用Predicate<Color> 而不是单个特定的Color,例如像这样:
class PdfGraphicsRemoverByColorPredicate extends PdfCanvasEditor {
public PdfGraphicsRemoverByColorPredicate(Predicate<Color> colorPredicate) {
this.colorPredicate = colorPredicate;
}
@Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands)
{
String operatorString = operator.toString();
if (colorPredicate.test(getGraphicsState().getFillColor())) {
switch (operatorString) {
case "f":
case "f*":
case "F":
operatorString = "n";
break;
case "b":
case "b*":
operatorString = "s";
break;
case "B":
case "B*":
operatorString = "S";
break;
}
}
if (colorPredicate.test(getGraphicsState().getStrokeColor())) {
switch (operatorString) {
case "s":
case "S":
operatorString = "n";
break;
case "b":
case "B":
operatorString = "f";
break;
case "b*":
case "B*":
operatorString = "f*";
break;
}
}
operator = new PdfLiteral(operatorString);
operands.set(operands.size() - 1, operator);
super.write(processor, operator, operands);
}
final Predicate<Color> colorPredicate;
}
(RemoveGraphicsByColor 助手类)
这样应用:
try ( PdfReader pdfReader = new PdfReader(INPUT);
PdfWriter pdfWriter = new PdfWriter(OUTPUT);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new PdfGraphicsRemoverByColorPredicate(RemoveGraphicsByColor::isRgbBlue);
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++)
{
editor.editPage(pdfDocument, i);
}
}
(RemoveGraphicsByColortestRemoveAllBlueLinesFrom* 测试)
到使用这个谓词方法的新示例文件
public static boolean isRgbBlue(Color color) {
if (color instanceof CalRgb || color instanceof DeviceRgb || (color instanceof IccBased && color.getNumberOfComponents() == 3)) {
float[] components = color.getColorValue();
float r = components[0];
float g = components[1];
float b = components[2];
return b > .5f && r < .9f*b && g < .9f*b;
}
return false;
}
(RemoveGraphicsByColor 辅助方法)
一个得到
和
请注意,上面的警告仍然适用。