【问题标题】:Removing watermark from pdf generated from MS-WORD从 MS-WORD 生成的 pdf 中删除水印
【发布时间】:2016-10-05 09:45:38
【问题描述】:

我正在寻找从 MS-WORD 生成的 PDF 中删除 watermark 的解决方案, 我使用了以下link 的解决方案,这适用于具有从 Itext pdf 生成的水印的文件

【问题讨论】:

  • 该链接需要注册。没门。您想要 itext 或 pdfbox 的解决方案吗?所有文件都是由同一来源生成的吗?
  • @saurabhiitr 据我所知,可以创建一个不需要注册访问的公共 Dropbox 共享。请这样做。
  • @TilmanHausherr 解决方案欢迎来自任何 Api ....

标签: itext pdfbox watermark


【解决方案1】:

这是一个 Apache PDFBox 解决方案,仅适用于您的文件。它很可能不适用于其他word文件,但值得一试。要了解我所做的,请使用 PDFBox PDFDebugger 命令行应用程序(或使用 itext RUPS)打开旧文件和新文件,然后查看“内容”条目。

我删除的部分开头是

/Artifact << /Attached [ /Top ] /Type /Pagination /Subtype /Header >> BDC

结尾
EMC

但是,那个也包含颜色和字体设置,所以我保留了这些。有可能在一个真实的文件中,这个段会包含更多有用的数据(毕竟它被命名为“Header”)和不同类型的颜色设置,所以需要更多的逻辑。

PDDocument document = PDDocument.load(new File("Saura.pdf"));
if (document.isEncrypted())
{
    System.err.println("Error: Encrypted documents are not supported for this example.");
    System.exit(1);
}
for (PDPage page : document.getPages())
{
    PDFStreamParser parser = new PDFStreamParser(page);
    parser.parse();
    List<Object> tokens = parser.getTokens();
    List<Object> newTokens = new ArrayList<Object>();
    List<Object> parameters = new ArrayList<Object>();
    boolean skip = false;
    // PDF content stream tokens have the forn
    // paramater1...parameterN operator
    for (Object token : tokens)
    {
        if (token instanceof Operator)
        {
            Operator op = (Operator) token;
            if ("BDC".equals(op.getName()))
            {
                // "Watermark" starts with
                // /Artifact << /Attached [ /Top ] /Type /Pagination /Subtype /Header >> BDC
                if (parameters.size() == 2 && COSName.ARTIFACT.equals(parameters.get(0)) && parameters.get(1) instanceof COSDictionary)
                {
                    COSDictionary dict = (COSDictionary) parameters.get(1);
                    if (COSName.getPDFName("Header").equals(dict.getItem(COSName.SUBTYPE)))
                    {
                        skip = true;
                    }
                }
            }
            if (!skip || "g".equals(op.getName()) || "G".equals(op.getName()) || "Tf".equals(op.getName()))
            {
                // even when skipping, don't remove color and font settings
                newTokens.addAll(parameters);
                newTokens.add(op);
            }
            if ("EMC".equals(op.getName()))
            {
                // "Watermark" ends with EMC
                skip = false;                            
            }
            parameters = new ArrayList<Object>();
        }
        else
        {
            parameters.add(token);
        }
    }
    PDStream newContents = new PDStream(document);
    OutputStream out = newContents.createOutputStream(COSName.FLATE_DECODE);
    ContentStreamWriter writer = new ContentStreamWriter(out);
    writer.writeTokens(newTokens);
    out.close();
    page.setContents(newContents);
}
document.save(new File("Saura2.pdf"));

【讨论】:

    【解决方案2】:

    我刚刚在 Kotlin 中写了一段代码来去除水印。 我对 PDF 一无所知,但希望对您有所帮助。

        @Test
        fun test() {
            val pdf = PDDocument.load(File("/tmp/original.pdf"))
    
            pdf.pages.forEachIndexed { index, p ->
                val tokens = ArrayList(PDFStreamParser(p).apply { parse() }.tokens)
                val found = tokens.indexOfLast {
                    it is COSDictionary && it.toString().contains("Watermark")
                }
                if (found >= 0) {
                    runCatching {
                        val start = (found downTo 0).first { i ->
                            tokens[i].let { it is Operator && it.name == "Q" }
                        }
                        val end = (found until tokens.size).first { i ->
                            tokens[i].let { it is Operator && it.name == "Q" }
                        }
                        //remove unwanted
                        tokens.subList(start, end).clear()
    
                        p.setContents(PDStream(pdf).apply {
                            createOutputStream(COSName.FLATE_DECODE).use {
                                ContentStreamWriter(it).writeTokens(tokens)
                            }
                        })
                    }.onFailure {
                        //debug something.
                        println("err: $p, $index")
                        throw it
                    }
                }
            }
    
            pdf.save(File("/tmp/output.pdf"))
        }
    
    

    【讨论】:

      猜你喜欢
      • 2016-06-02
      • 2012-02-04
      • 1970-01-01
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      相关资源
      最近更新 更多