2012-01-19 25 views
14

Tôi đang cố thêm hình mờ vào PDF cụ thể với PDFBox. Tôi đã có thể làm cho hình ảnh xuất hiện trên mỗi trang, nhưng nó mất tính trong suốt của nền vì nó xuất hiện như thể PDJpeg chuyển đổi nó sang JPG. Có lẽ có một cách để làm điều đó bằng cách sử dụng PDXObjectImage.Watermarking với PDFBox

Dưới đây là những gì tôi đã viết như vậy, cho đến nay:

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(); 
    } 
} 
+0

Vấn đề với câu trả lời dưới đây là vị trí không hoạt động như tôi mong đợi (trên cùng bên trái hợp lý) nếu các trang có kích thước khác nhau. Tôi cần phải thêm một watermark văn bản vào đầu mỗi trang trong một tài liệu PDF, và các giải pháp trên là chính xác những gì tôi cần, do đó, bumping giải pháp này lên. –

Trả lời

26

CẬP NHẬT ĐÁP (phiên bản tốt hơn với cách dễ dàng để watermark, nhờ các nhà bình luận dưới đây và @okok người cung cấp đầu vào với câu trả lời của mình)

Nếu bạn đang sử dụng PDFBox 1.8.10 hoặc cao hơn, bạn có thể thêm watermark vào tài liệu PDF của mình một cách dễ dàng với sự kiểm soát tốt hơn đối với những trang cần được watermarked. Giả sử bạn có một tài liệu PDF một trang có hình mờ, bạn có thể che phủ hình ảnh này trên tài liệu bạn muốn đóng dấu như sau.

Mẫu Mã sử ​​dụng 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<Integer, String> overlayGuide = new HashMap<Integer, String>(); 
      for(int i=0; i<realDoc.getPageCount(); i++){ 
       overlayGuide.put(i+1, "watermark.pdf"); 
       //watermark.pdf is the document which is a one page PDF with your watermark image in it. Notice here that you can skip pages from being watermarked. 
      } 
      Overlay overlay = new Overlay(); 
      overlay.setInputPDF(realDoc); 
      overlay.setOutputFile("final.pdf"); 
      overlay.setOverlayPosition(Overlay.Position.BACKGROUND); 
      overlay.overlay(overlayGuide,false); 
      //final.pdf will have the original PDF with watermarks. 

mẫu sử dụng 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<Integer, String> overlayGuide = new HashMap<Integer, String>(); 
     for(int i=0; i<realDoc.getNumberOfPages(); i++){ 
      overlayGuide.put(i+1, "watermark.pdf"); 
      //watermark.pdf is the document which is a one page PDF with your watermark image in it. 
      //Notice here, you can skip pages from being watermarked. 
     } 
     Overlay overlay = new Overlay(); 
     overlay.setInputPDF(realDoc); 
     overlay.setOutputFile("final.pdf"); 
     overlay.setOverlayPosition(Overlay.Position.BACKGROUND); 
     overlay.overlay(overlayGuide);  
    } 
} 

OLD ĐÁP cách không hiệu quả, không được khuyến khích.

Vâng, OP đã hỏi làm thế nào để làm điều đó trong PDFBox, câu trả lời đầu tiên trông giống như một ví dụ sử dụng iText. Tạo hình mờ trong PDFBox thực sự đơn giản. Bí quyết là, bạn nên có một tài liệu PDF trống với hình mờ. Sau đó, tất cả những gì bạn phải làm là Overlay tài liệu watermark này trên tài liệu mà bạn muốn thêm watermark vào.

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"); 

Thận trọng: Bạn nên chắc chắn rằng bạn khớp với số trang trong cả hai tài liệu .. Nếu không, bạn sẽ kết thúc với một số trang phù hợp với số trang có số trang ít nhất. Bạn có thể thao tác tài liệu watermark và sao chép các trang để khớp với tài liệu của bạn.

Hy vọng điều này sẽ giúp.!

+0

Xin lỗi vì trả lời trễ (dự án đã bị tạm giữ). Tôi đã thử triển khai mã này, nhưng tôi nhận được một trong hai vấn đề: (1) Tôi đã sử dụng 1 trang PDF và 1 trang watermark PDF, nhưng hình mờ là thứ duy nhất hiển thị trên tài liệu cuối cùng vấn đề minh bạch?) (2) Tôi đã thử một trang 2 PDF với một PDF 2 trang watermark và tiếp tục nhận được "Bố trí các trang với COSArray hiện không được hỗ trợ." Tôi không thể tìm thấy bất kỳ tài liệu nào về nó hoặc cách thay đổi tài liệu nhiều trang thành một định dạng phù hợp hơn. – aosmith

+0

Sau khi chơi xung quanh với điều này một số chi tiết, nó có vẻ làm việc tốt, nhưng theo kịch bản cụ thể chỉ. Hình mờ dường như không hoạt động tốt nếu nó là bất kỳ thứ gì khác ngoài văn bản (cũng không thể làm việc trong suốt). Lớp phủ cũng không thể có COSArray trong đó (mà tôi vẫn không chắc chắn nó xuất phát từ đâu, có lẽ liên quan đến dấu trang hoặc văn bản). – aosmith

+0

Xin chào - Có giải pháp nào để watermark các trang cụ thể trên PDF chứ không phải tất cả chúng? –

-3

Nhìn vào phương pháp này, whitch thêm một watermark hình ảnh trong các nguồn pdf sử dụng thư viện PDFBOX

/** 
    * 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(); 
    } 
+2

Điều này là dành cho iText –

+0

Bạn sẽ làm điều này với Rails bằng cách nào? –

9

Chỉ cần thực hiện đoạn mã này để thêm hình ảnh (trong suốt) (jpg, png, gif) đến một trang pdf với pdfbox:

/** 
* Draw an image to the specified coordinates onto a single page. <br> 
* 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 (e.g. 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(); 
} 

Ví dụ:

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"); 
} 

này làm việc cho tôi với jdk 1.7 và bcmail-jdk16-140.jar, bcprov-jdk16-140.jar, commons-logging-1.1.3.jar, fontbox-1.8.3.jar, jempbox-1.8.3.jar và pdfbox-1.8. 3.jar.

+0

Nếu sử dụng Android không hỗ trợ BufferedImage và PdfBox-Android phiên bản 1.8.9.1 chưa có PDPixelMap, PDXObjectImage có thể được tạo từ bitmap: PDImageXObject ximage = LosslessFactory.createFromImage (tài liệu, bitmap); – jk7

0

Có một lớp Lớp phủ khác trong gói util, giúp bạn tiết kiệm từ việc tạo pdf với cùng số trang như tài liệu nguồn và sau đó thực hiện lớp phủ.

Để hiểu cách sử dụng của nó, hãy xem mã nguồn của pdfbox, đặc biệt là lớp OverlayPDF.

2

@Androidman: bổ sung https://stackoverflow.com/a/9382212/7802973

Nó có vẻ như nhiều phương pháp được loại bỏ với mỗi phiên bản của PDFBox. Vì vậy, mã sẽ không hoạt động trên 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") 

Thay vào đó, sử dụng void org.apache.pdfbox.pdmodel.PDDocument.save(String fileName), tôi nghĩ rằng:

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<Integer, String> overlayGuide = new HashMap<Integer, String>(); 
    for(int i=0; i<realDoc.getNumberOfPages(); i++){ 
     overlayGuide.put(i+1, "watermark.pdf"); 
     //watermark.pdf is the document which is a one page PDF with your watermark image in it. 
     //Notice here, you can skip pages from being watermarked. 
    } 
Overlay overlay = new Overlay(); 
overlay.setInputPDF(realDoc); 
overlay.overlay(overlayGuide).save("final.pdf"); 
overlay.close(); 

Edit: Tôi đang sử dụng org.apache.pdfbox.tools.OverlayPDF cho lớp phủ bây giờ và nó hoạt động tốt. Mã này trông như thế này:

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

Như tôi đã không đủ uy tín để thêm một bình luận, tôi nghĩ rằng nó muốn được thích hợp để thêm video này trong một câu trả lời mới.

Các vấn đề liên quan