使用PDFBox加水印

我正在尝试使用PDFBox专门为PDF添加水印。 我已经能够让图像显示在每个页面上,但它会失去背景透明度,因为它看起来好像PDJpeg将其转换为JPG。 也许有一种方法可以使用PDXObjectImage来完成它。

这是我到目前为止所写的内容:

public static void watermarkPDF(PDDocument pdf) throws IOException { // Load watermark BufferedImage buffered = ImageIO.read(new File("C:\\PDF_Test\\watermark.png")); PDJpeg watermark = new PDJpeg(pdf, buffered); // Loop through pages in PDF List pages = pdf.getDocumentCatalog().getAllPages(); Iterator iter = pages.iterator(); while(iter.hasNext()) { PDPage page = (PDPage)iter.next(); // Add watermark to individual page PDPageContentStream stream = new PDPageContentStream(pdf, page, true, false); stream.drawImage(watermark, 100, 0); stream.close(); } try { pdf.save("C:\\PDF_Test\\watermarktest.pdf"); } catch (COSVisitorException e) { e.printStackTrace(); } } 

更新的答案 (更好的版本,简单的水印方式,感谢下面的评论员和@okok提供输入他的答案)

如果您使用的是PDFBox 1.8.10或更高版本,则可以轻松地为PDF文档添加水印,从而更好地控制需要加水印的页面。 假设您有一个带有水印图像的单页PDF文档,您可以将其叠加在要添加水印的文档上,如下所示。

示例代码使用1.8.10

 import java.util.HashMap; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.util.Overlay; public class TestPDF { public static void main(String[] args) throws Exception{ PDDocument realDoc = PDDocument.load("originaldocument.pdf"); //the above is the document you want to watermark //for all the pages, you can add overlay guide, indicating watermark the original pages with the watermark document. HashMap overlayGuide = new HashMap(); for(int i=0; i 

使用PDFBox 2.0.0 Release candidate的示例

 import java.io.File; import java.util.HashMap; import org.apache.pdfbox.multipdf.Overlay; import org.apache.pdfbox.pdmodel.PDDocument; public class TestPDF { public static void main(String[] args) throws Exception{ PDDocument realDoc = PDDocument.load(new File("originaldocument.pdf")); //the above is the document you want to watermark //for all the pages, you can add overlay guide, indicating watermark the original pages with the watermark document. HashMap overlayGuide = new HashMap(); for(int i=0; i 

如果要使用新包org.apache.pdfbox.tools.OverlayPDF进行叠加,可以这样做。 (感谢下面的海报)

 String[] overlayArgs = {"C:/Examples/foreground.pdf", "C:/Examples/background.pdf", "C:/Examples/resulting.pdf"}; OverlayPDF.main(overlayArgs); System.out.println("Overlay finished."); 

老答案效率不高,不推荐。

好吧,OP询问如何在PDFBox中执行此操作,第一个答案看起来像是使用iText的示例。 在PDFBox中创建水印非常简单。 诀窍是,你应该有一个带有水印图像的空PDF文档。 然后,您所要做的就是在要添加水印的文档上覆盖此水印文档。

 PDDocument watermarkDoc = PDDocument.load("watermark.pdf"); //Assuming your empty document with watermark image in it. PDDocument realDoc = PDDocument.load("document-to-be-watermarked.pdf"); //Let's say this is your document that you want to watermark. For example sake, I am opening a new one, you would already have a reference to PDDocument if you are creating one Overlay overlay = new Overlay(); overlay.overlay(realDoc,watermarkDoc); watermarkDoc.save("document-now-watermarked.pdf"); 

警告:您应确保匹配两个文档中的页数。否则,您最终会得到一个文档,其页数与页数最少的页面相匹配。 您可以操作水印文档并复制页面以匹配您的文档。

希望这可以帮助。!

刚刚制作了这段代码,用pdfbox将(透明)图像(jpg,png,gif)添加到pdf页面:

 /** * Draw an image to the specified coordinates onto a single page. 
* Also scaled the image with the specified factor. * * @author Nick Russler * @param document PDF document the image should be written to. * @param pdfpage Page number of the page in which the image should be written to. * @param x X coordinate on the page where the left bottom corner of the image should be located. Regard that 0 is the left bottom of the pdf page. * @param y Y coordinate on the page where the left bottom corner of the image should be located. * @param scale Factor used to resize the image. * @param imageFilePath Filepath of the image that is written to the PDF. * @throws IOException */ public static void addImageToPage(PDDocument document, int pdfpage, int x, int y, float scale, String imageFilePath) throws IOException { // Convert the image to TYPE_4BYTE_ABGR so PDFBox won't throw exceptions (eg for transparent png's). BufferedImage tmp_image = ImageIO.read(new File(imageFilePath)); BufferedImage image = new BufferedImage(tmp_image.getWidth(), tmp_image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR); image.createGraphics().drawRenderedImage(tmp_image, null); PDXObjectImage ximage = new PDPixelMap(document, image); PDPage page = (PDPage)document.getDocumentCatalog().getAllPages().get(pdfpage); PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true); contentStream.drawXObject(ximage, x, y, ximage.getWidth()*scale, ximage.getHeight()*scale); contentStream.close(); }

例:

 public static void main(String[] args) throws Exception { String pdfFilePath = "C:/Users/Nick/Desktop/pdf-test.pdf"; String signatureImagePath = "C:/Users/Nick/Desktop/signature.png"; int page = 0; PDDocument document = PDDocument.load(pdfFilePath); addImageToPage(document, page, 0, 0, 0.5f, signatureImagePath); document.save("C:/Users/Nick/Desktop/pdf-test-neu.pdf"); } 

这适用于jdk 1.7和bcmail-jdk16-140.jar,bcprov-jdk16-140.jar,commons-logging-1.1.3.jar,fontbox-1.8.3.jar,jempbox-1.8.3.jar和PDFBOX-1.8.3.jar。

@Androidman:加入https://stackoverflow.com/a/9382212/7802973

似乎每个版本的PDFBox都删除了许多方法。 因此该代码不适用于PDFBox 2.0.7。

 Overlay overlay = new Overlay(); overlay.setInputPDF(realDoc); // ** The method setOutputFile(String) is undefined for the type Overlay ** overlay.setOutputFile("final.pdf") 

相反,使用void org.apache.pdfbox.pdmodel.PDDocument.save(String fileName) ,我认为:

 PDDocument realDoc = PDDocument.load(new File("originaldocument.pdf")); //the above is the document you want to watermark //for all the pages, you can add overlay guide, indicating watermark the original pages with the watermark document. HashMap overlayGuide = new HashMap(); for(int i=0; i 

编辑:我现在使用org.apache.pdfbox.tools.OverlayPDF进行叠加,它运行正常。 代码如下所示:

 String[] overlayArgs = {"C:/Examples/foreground.pdf", "C:/Examples/background.pdf", "C:/Examples/resulting.pdf"}; OverlayPDF.main(overlayArgs); System.out.println("Overlay finished."); 

由于我没有足够的声誉来添加评论,我认为将其添加到新答案中是合适的。

util包中还有另一个Overlay类,它可以帮助您避免创建与源文档具有相同页数的pdf,然后进行覆盖。

要了解其用法,请查看pdfbox源代码,特别是OverlayPDF类。

看看这个方法,使用PDFBOX库在pdf源中添加水印图像

 /** * Coloca una imagen como marca de agua en un pdf en una posición especifica * * @param buffer * flujo de bytes que contiene el pdf original * * @param imageFileName * nombre del archivo de la imagen a colocar * * @param x * posición x de la imagen en el pdf * * @param y * posición y de la imagen en el pdf * * @param under * determina si la marca se pone encima o por debajo de la factura * * @return flujo de bytes resultante que contiene el pdf modificado * * @throws IOException * @throws DocumentException */ public static byte[] addWaterMarkImageToPDF(byte[] buffer, String imageFileName, int x, int y, boolean under) throws IOException, DocumentException { logger.debug("Agregando marca de agua:"+imageFileName); PdfReader reader = new PdfReader(buffer); ByteArrayOutputStream arrayOutput = new ByteArrayOutputStream(); OutputStream output = new BufferedOutputStream(arrayOutput); PdfStamper stamper = new PdfStamper(reader, output); com.lowagie.text.Image img = com.lowagie.text.Image .getInstance(imageFileName); img.setAbsolutePosition(x, y); img.scalePercent(SCALE_PER); PdfContentByte pdfContent; int total = reader.getNumberOfPages() + 1; for (int i = 1; i < total; i++) { pdfContent = (under)?stamper.getUnderContent(i): stamper.getOverContent(i); pdfContent.addImage(img); } stamper.close(); output.flush(); output.close(); return arrayOutput.toByteArray(); }