如何在现有PDF中使文本不可见

时间:2014-02-12 06:57:49

标签: java pdf itext

我想让现有PDF中的所有文字都透明。

选项1:选择所有文本,找到颜色属性并将其更改为“无色”

或者,如果没有这样的财产

选项2:解析页面内容Stream和该页面的所有Form XObjects,检测文本块(BT / ET),并将渲染模式设置为invisble。

这似乎是一项复杂的操作。

这是我的example file

以下代码生成PDF(示例pdf文件):

    Document document = new Document(new Rectangle(width, height));
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
    document.open();

    PdfContentByte picCanvas = null;
    PdfContentByte txtCanvas = null;
    if (isUnderPic) {
        txtCanvas = writer.getDirectContentUnder();
        picCanvas = writer.getDirectContent();
    } else {
        txtCanvas = writer.getDirectContent();
        picCanvas = writer.getDirectContentUnder();
    }
    BaseFont bf = null;
    if (null != pageList) {

        int[] dpi = { 0, 0 };
        if (dpiType == 1) {
            dpi[0] = 300;
            dpi[1] = 300;
        } else if (dpiType == 2) {
            dpi[0] = 600;
            dpi[1] = 600;
        }

        for (int i = 0; i < pageList.size(); i++) {
            PDFPage page = pageList.get(i);
            Image pageImage = null;
            if (pdfType == 3) {
                pageImage = Image.getInstance(page.getBinImage());
            } else {
                pageImage = Image.getInstance(page.getOriImage());
            }
            if (pageImage.getWidth() > 0) {
                pageImage.scaleAbsolute(page.getWidth(), page.getHeight());
            }
            pageImage.setAbsolutePosition(0, 0);
            picCanvas.addImage(pageImage);

            if (pdfType == 2 || pdfType == 3) {
                for (PageElement ele : page.getElementList()) {
                    if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_CHAR)) {
                        txtCanvas.beginText();
                        if (isColor) {
                            txtCanvas.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
                            txtCanvas.setColorFill(BaseColor.RED);
                        } else {
                            txtCanvas.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_INVISIBLE);
                        }

                        String font = ele.getFont();
                        try {
                            bf = fonts.get(font);
                            if (null == bf) {
                                bf = BaseFont.createFont(font, "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                                fonts.put(font, bf);
                            }
                        } catch (Exception e) {
                            bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                            fonts.put(font, bf);
                        }
                        txtCanvas.setFontAndSize(bf, ele.getFontSize());
                        txtCanvas.setTextMatrix(ele.getPageX(), ele.getPageY(page.getRcInPage()));
                        txtCanvas.showText(ele.getCode());
                        txtCanvas.endText();
                    }
                }
            }

            if (StringUtils.isNotBlank(cutPath)) {
                for (PageElement ele : page.getElementList()) {
                    if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_PIC) && StringUtils.isNotBlank(ele.getCutPicSrc())) {
                        ImageTools.cutPic(ele.getRcInImage(), page.getOriImage(), ele.getCutPicSrc(), dpi);
                    }
                }
            }
            if (pdfType == 3) {
                logger.debug("pdfType == 3");
                for (PageElement ele : page.getElementList()) {
                    if (ele.getType().equals(PDFConstant.ElementType.PDF_ELEMENT_PIC) && StringUtils.isNotBlank(ele.getCutPicSrc())) {
                        if (new File(ele.getCutPicSrc()).exists()) {
                            Image cutCover = Image.getInstance(ImageTools.drawImage((int) ele.getWidth(), (int) ele.getHeight()));
                            if (cutCover.getWidth() > 0) {
                                cutCover.scaleAbsolute(ele.getWidth(), ele.getHeight());
                            }
                            cutCover.setAbsolutePosition(ele.getPageX(), ele.getPageY(page.getRcInPage()));
                            picCanvas.addImage(cutCover);
                            Image pic = Image.getInstance(ele.getCutPicSrc());
                            if (pic.getWidth() > 0) {
                                pic.scaleAbsolute(ele.getWidth(), ele.getHeight());
                            }
                            pic.setAbsolutePosition(ele.getPageX(), ele.getPageY(page.getRcInPage()));
                            picCanvas.addImage(pic);
                        }
                    }
                }
            }
            if (i + 1 < pageList.size()) {
                document.setPageSize(new Rectangle(pageList.get(i + 1).getWidth(), pageList.get(i + 1).getHeight()));
            } else {
                document.setPageSize(new Rectangle(pageList.get(i).getWidth(), pageList.get(i).getHeight()));
            }
            document.newPage();
        }
    }
    document.close();

1 个答案:

答案 0 :(得分:2)

我看过你的PDF,我发现PDF是扫描图像。文本不是真正的文本:它由图像组成。您的问题无效,因为它假定文本由矢量数据组成(使用PDF语法定义,例如BTET)。实际上,文本是一堆像素,任何像素都不知道它是属于文本字形还是图像。简而言之:你使用了错误的方法。您正在尝试使用PDF软件解决问题,而您应该使用操作光栅图像的工具。

这是我从PDF中提取的图像:

enter image description here

OP宣称有两层:一层有图像,一层有文字。这可能是真的,但图像也包含光栅化文本,并且无法通过更改PDF语法从图像中删除该文本。

如果您知道坐标,您可以覆盖文本,但这在很大程度上取决于OCR操作的准确性。

如果您的要求不是覆盖图像中的文本,而是覆盖矢量图层的文本,则添加在添加矢量文本的语法之后添加图像的语法就足够了。如果图像不透明,它将覆盖所有文本。这是在RepeatImage示例中完成的:

PdfReader reader = new PdfReader(src);
// We assume that there's a single large picture on the first page
PdfDictionary page = reader.getPageN(1);
PdfDictionary resources = page.getAsDict(PdfName.RESOURCES);
PdfDictionary xobjects = resources.getAsDict(PdfName.XOBJECT);
PdfName imgName = xobjects.getKeys().iterator().next();
Image img = Image.getInstance((PRIndirectReference)xobjects.getAsIndirectObject(imgName));
img.setAbsolutePosition(0, 0);
img.scaleAbsolute(reader.getPageSize(1));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.getOverContent(1).addImage(img);
stamper.close();
reader.close();

看看resulting PDF;现在你仍然可以选择矢量文本,但它不再可见。