001    package railo.runtime.text.pdf;
002    
003    import java.awt.image.BufferedImage;
004    import java.io.ByteArrayInputStream;
005    import java.io.File;
006    import java.io.FileOutputStream;
007    import java.io.IOException;
008    import java.io.RandomAccessFile;
009    import java.nio.ByteBuffer;
010    import java.nio.channels.FileChannel;
011    import java.util.Set;
012    
013    import railo.commons.io.IOUtil;
014    import railo.commons.io.res.Resource;
015    import railo.runtime.exp.ExpressionException;
016    import railo.runtime.exp.PageException;
017    import railo.runtime.img.Image;
018    
019    import com.sun.pdfview.PDFFile;
020    import com.sun.pdfview.PDFPage;
021    
022    public class PDF2ImagePDFRenderer extends PDF2Image {
023            
024            public PDF2ImagePDFRenderer(){
025                    PDFFile.class.getName();// this is needed, that the class throws a error when the PDFRenderer.jar is not in the enviroment
026            }
027    
028            /**
029             * @see railo.runtime.text.pdf.PDF2Image#toImage(byte[], int)
030             */
031            public Image toImage(byte[] input, int pageNumber) throws IOException {
032                    
033                    File file = File.createTempFile("pdf2img", "pdf");
034                    
035                    try{
036                            copy(input,file);
037                            PDFFile pdffile = toPDFFile(file);
038                            
039                    // draw a single page to an image
040                            PDFPage page = pdffile.getPage(pageNumber);
041                    
042                    return toImage(page,(int)page.getBBox().getWidth(),(int)page.getBBox().getHeight(),false);
043                  
044                    
045                    }
046                    finally{
047                            deleteEL(file);
048                    }
049            }
050    
051            private static Image toImage(PDFPage page, int width, int height,boolean transparent) {
052                    int w = (int)page.getBBox().getWidth();
053                    int h = (int)page.getBBox().getHeight();
054                    java.awt.Rectangle rect = new java.awt.Rectangle(0,0,w,h);
055            
056            BufferedImage bi = Image.toBufferedImage(page.getImage(
057                    width, height, //width & height
058                    rect, // clip rect
059                    null, // null for the ImageObserver
060                    !transparent, // fill background with white
061                    true  // block until drawing is done
062                    ));
063            
064            return new Image(bi);
065            }
066    
067            /**
068             * @see railo.runtime.text.pdf.PDF2Image#writeImages(byte[], java.util.Set, railo.commons.io.res.Resource, java.lang.String, java.lang.String, int, boolean, boolean, boolean)
069             */
070            public void writeImages(byte[] input, Set pages, Resource outputDirectory,
071                            String prefix, String format, int scale, boolean overwrite,
072                            boolean goodQuality, boolean transparent) throws PageException,
073                            IOException {
074                    
075    
076                    File file = File.createTempFile("pdf2img", "pdf");
077                    try{
078                            copy(input,file);
079                            PDFFile pdf = toPDFFile(file);
080                    
081                            Resource res;
082                            int count = pdf.getNumPages();
083                             
084                            for(int page=1;page<=count;page++) {
085                                    if(pages!=null && !pages.contains(Integer.valueOf(page)))continue;
086                                    res=createDestinationResource(outputDirectory,prefix,page,format,overwrite);
087                                    //res=outputDirectory.getRealResource(prefix+"_page_"+page+"."+format);
088                                    writeImage(pdf,page,res,format,scale,overwrite,goodQuality, transparent);
089                            }
090                    }
091                    finally{
092                            deleteEL(file);
093                    }
094            }
095            
096            private static void writeImage(PDFFile pdf, int pageNumber, Resource destination,String format, int scale,
097                            boolean overwrite, boolean goodQuality, boolean transparent) throws PageException, IOException {
098                    
099                    PDFPage page = pdf.getPage(pageNumber);
100                    
101                    if(scale<1) throw new ExpressionException("scale ["+scale+"] should be at least 1");
102                    
103                    int width = (int)page.getBBox().getWidth();
104                    int height = (int)page.getBBox().getHeight();
105                    if(scale!=100){
106                            double s=(scale)/100d;
107                            width=  (int)((width)*s);
108                            height= (int)((height)*s);
109                            
110                            
111                    }
112                    Image img=toImage(page, width, height,transparent);
113                    img.writeOut(destination,format, overwrite, 1f);
114            }
115    
116            private PDFFile toPDFFile(File file) throws IOException {
117                    RandomAccessFile raf = new RandomAccessFile(file, "r");
118            FileChannel channel = raf.getChannel();
119            ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
120            return new PDFFile(buf);
121    
122            }
123    
124            private void deleteEL(File file) {
125                    try{
126                    if(!file.delete())file.deleteOnExit();
127                    }
128                    catch(Throwable t){}
129            }
130    
131            private void copy(byte[] input, File file) throws IOException {
132                    ByteArrayInputStream bais = new ByteArrayInputStream(input);
133                    FileOutputStream fos = new FileOutputStream(file);
134                    IOUtil.copy(bais, fos, true,true);
135                    
136            }
137    
138    }