2013-10-17 189 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