2013-10-17 241 views
1

我正在處理一個用戶故事,要求能夠將所有現有的打印輸出爲PDF文件。要做到這一點,我渲染java.awt.PrintableBufferedImage並把這個圖像到使用Apache的一個PDFBox的PDF,但我有一對夫婦使用這種方法的問題:將可打印文件轉換爲PDF

  • 如果我使用PDJPeg圖像變得模糊。
  • 如果我使用PDPixelMap,則生成的PDF是完全黑色的。

我能想到的唯一的另一種方法是做一個接口,即Printer,然後做兩個子類,即PhysicalPrinterPDFPrinter但這需要我重新實現所有現有java.awt.Printable s到使用這個新的接口。

這裏是我當前的打印到PDF方法SSCCE:

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.awt.print.PageFormat; 
import java.awt.print.Printable; 
import java.awt.print.PrinterException; 
import java.io.File; 
import java.util.Random; 

import javax.imageio.ImageIO; 

import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.PDPage; 
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; 
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; 

public class Printer { 
    private Printer() {} 
    public static boolean printToPDF(String file, Printable printable) { 
     try { 
      PageFormat pageFormat = new PageFormat(); 
      PDDocument doc = new PDDocument(); 
      int width = (int)(pageFormat.getWidth()); 
      int height = (int)(pageFormat.getHeight()); 

      int currentPage = 0; 
      while(true) { 
       BufferedImage image = new BufferedImage(width, height, 
                 BufferedImage.TYPE_INT_RGB); 
       Graphics2D g2d = image.createGraphics(); 
       g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON); 
       g2d.setColor(Color.WHITE); 
       g2d.fillRect(0, 0, width, height); 
       g2d.setColor(Color.BLACK); 
       g2d.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12)); 

       if(printable.print(g2d, pageFormat, currentPage) == Printable.NO_SUCH_PAGE) { 
        break; 
       } 
       ImageIO.write(image, "png", new File("test.png")); 

       PDPage page = new PDPage(); 
       doc.addPage(page); 

       PDJpeg img = new PDJpeg(doc, image); //Blurry 
       //PDPixelMap img = new PDPixelMap(doc, image); //Black 
       PDPageContentStream content = new PDPageContentStream(doc, page); 
       content.drawImage(img, 0, 0); 
       content.close(); 

       ++currentPage; 
      } 

      doc.save(file); 
      doc.close(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 

     return true; 
    } 
    public static void main(String[] args) { 
     Printable printable = new Printable() { 
      @Override 
      public int print(Graphics g, PageFormat pf, int index) 
      throws PrinterException { 
       if(index > 0) { 
        return NO_SUCH_PAGE; 
       } 

       Graphics2D g2d = (Graphics2D)g; 
       g2d.translate(pf.getImageableX(), pf.getImageableY()); 
       Random rand = new Random(); 

       for(int i = 0; i < 30; ++i) { 
        int x = rand.nextInt((int)pf.getImageableWidth()); 
        int y = rand.nextInt((int)pf.getImageableHeight()); 

        g2d.drawString("Test", x, y); 
       } 

       return PAGE_EXISTS; 
      } 
     }; 

     printToPDF("Test.pdf", printable); 
    } 
} 

編輯

我設法解決黑PDPixelMap,則下跌至BUfferedImage使用錯誤圖像類型。我將它從BufferedImage.TYPE_INT_RGB更改爲BufferedImage.TYPE_4BYTE_ABGR。不幸的是,由此產生的PDF仍然是模糊的。

+1

此問題將在即將發佈的1.8.5版本中修復,請參閱https://issues.apache.org/jira/browse/PDFBOX-2030。它已經在2.0版本(具有不同的API)中得到修復,請參閱https://issues.apache.org/jira/browse/PDFBOX-1990。你可以從svn獲得兩個。 –

回答

0

我認爲可能對你有幫助的兩個框架是ITextPDFRenderer。 IText是免費的4.2版本(如果我沒有記錯的話),PDFRenderer是LGPL 2.1許可證。例如,最好看一下網上的教程。我認爲兩者都是你想要完成的可行解決方案。我個人使用PDFRenderer。

+0

根據我的理解,PDFRenderer上的文檔看起來很缺乏(不存在?),免費版本的IText許可證需要公開源代碼來使用它。 – Lerp

+0

我會再次看看IText許可證,但如果你只是谷歌的PDFRenderer和教程或例子,你會發現一些東西! – LastFreeNickname