如何使用pdfbox检查文本是否透明

PDFStreamEngine并重载了processTextPosition ,我现在能够重建像PDFTextStripper这样的文本,但我不想处理透明文本,这通常是垃圾。

我怎么知道某些文字是否透明?

事实certificate, 透明文本实际上根本不是透明的,而只是被图像所覆盖:2 0110年SA 2010年的主要吸烟统计数据FINAL.pdf文字“SA的主要吸烟统计数据— 2004”已被图像覆盖显示TC徽标。

下面显示了文本剥离器类忽略图像覆盖的文本的概念certificate。

 public class VisibleTextStripper extends PDFTextStripper { public VisibleTextStripper() throws IOException { super(); registerOperatorProcessor("Do", new Invoke()); } // // Hiding operations // void hide(String name) { Matrix ctm = getGraphicsState().getCurrentTransformationMatrix(); float x = ctm.getXPosition(); float y = ctm.getYPosition(); float scaledWidth = ctm.getXScale(); float scaledHeight = ctm.getYScale(); for(List characters : charactersByArticle) { Collection toRemove = new ArrayList(); for (TextPosition character : characters) { Matrix matrix = character.getTextPos(); float cx = matrix.getXPosition(); float cy = matrix.getYPosition(); float cw = character.getWidth(); float ch = character.getHeight(); if (overlaps(x, scaledWidth, cx, cw) && overlaps(y, scaledHeight, cy, cw)) { System.out.printf("Hidden by '%s': X: %f; Y: %f; Width: %f; Height: %f; Char: '%s'\n", name, cx, cy, cw, ch, character.getCharacter()); toRemove.add(character); } } characters.removeAll(toRemove); } } private boolean overlaps(float start1, float width1, float start2, float width2) { if (width1 < 0) { start1 += width1; width1 = -width1; } if (width2 < 0) { start2 += width2; width2 = -width2; } if (start1 < start2) { return start1 + width1 >= start2; } else { return start2 + width2 >= start1; } } // // operator processors // public static class Invoke extends OperatorProcessor { /** * Log instance. */ private static final Log LOG = LogFactory.getLog(Invoke.class); /** * process : Do : Paint the specified XObject (section 4.7). * @param operator The operator that is being executed. * @param arguments List * @throws IOException If there is an error invoking the sub object. */ public void process(PDFOperator operator, List arguments) throws IOException { VisibleTextStripper drawer = (VisibleTextStripper)context; COSName objectName = (COSName)arguments.get( 0 ); Map xobjects = drawer.getResources().getXObjects(); PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() ); if ( xobject == null ) { LOG.warn("Can't find the XObject for '"+objectName.getName()+"'"); } else if( xobject instanceof PDXObjectImage ) { drawer.hide(objectName.getName()); } else if(xobject instanceof PDXObjectForm) { PDXObjectForm form = (PDXObjectForm)xobject; COSStream formContentstream = form.getCOSStream(); // if there is an optional form matrix, we have to map the form space to the user space Matrix matrix = form.getMatrix(); if (matrix != null) { Matrix xobjectCTM = matrix.multiply( context.getGraphicsState().getCurrentTransformationMatrix()); context.getGraphicsState().setCurrentTransformationMatrix(xobjectCTM); } // find some optional resources, instead of using the current resources PDResources pdResources = form.getResources(); context.processSubStream( context.getCurrentPage(), pdResources, formContentstream ); } } } } 

它适用于您的示例文档。

支票

 if (overlaps(x, scaledWidth, cx, cw) && overlaps(y, scaledHeight, cy, cw)) 

不幸的是,假设没有涉及的旋转(所有变换聚合),文本和图像都没有。

对于通用解决方案,您必须将此测试更改为检查由Matrix ctm = getGraphicsState().getCurrentTransformationMatrix()转换的1×1平方Matrix ctm = getGraphicsState().getCurrentTransformationMatrix()与由Matrix matrix = character.getTextPos()具有固定宽度的字符框重叠并且height cw = character.getWidth()ch = character.getHeight() 。 也许简单的重叠是不够的,您可能希望充分覆盖字符框。

此外,该测试忽略了图像掩模,即图像的透明度。