001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.text.pdf;
020
021import java.awt.image.BufferedImage;
022import java.io.ByteArrayInputStream;
023import java.io.File;
024import java.io.FileOutputStream;
025import java.io.IOException;
026import java.io.RandomAccessFile;
027import java.nio.ByteBuffer;
028import java.nio.channels.FileChannel;
029import java.util.Set;
030
031import lucee.commons.io.IOUtil;
032import lucee.commons.io.res.Resource;
033import lucee.commons.lang.ExceptionUtil;
034import lucee.runtime.exp.ExpressionException;
035import lucee.runtime.exp.PageException;
036import lucee.runtime.img.Image;
037
038import com.sun.pdfview.PDFFile;
039import com.sun.pdfview.PDFPage;
040
041public class PDF2ImagePDFRenderer extends PDF2Image {
042        
043        public PDF2ImagePDFRenderer(){
044                PDFFile.class.getName();// this is needed, that the class throws a error when the PDFRenderer.jar is not in the enviroment
045        }
046
047        @Override
048        public Image toImage(byte[] input, int pageNumber) throws IOException {
049                
050                File file = File.createTempFile("pdf2img", "pdf");
051                
052                try{
053                        copy(input,file);
054                        PDFFile pdffile = toPDFFile(file);
055                        
056                // draw a single page to an image
057                        PDFPage page = pdffile.getPage(pageNumber);
058                
059                return toImage(page,(int)page.getBBox().getWidth(),(int)page.getBBox().getHeight(),false);
060              
061                
062                }
063                finally{
064                        deleteEL(file);
065                }
066        }
067
068        private static Image toImage(PDFPage page, int width, int height,boolean transparent) {
069                int w = (int)page.getBBox().getWidth();
070                int h = (int)page.getBBox().getHeight();
071                java.awt.Rectangle rect = new java.awt.Rectangle(0,0,w,h);
072        
073        BufferedImage bi = Image.toBufferedImage(page.getImage(
074                width, height, //width & height
075                rect, // clip rect
076                null, // null for the ImageObserver
077                !transparent, // fill background with white
078                true  // block until drawing is done
079                ));
080        
081        return new Image(bi);
082        }
083
084        @Override
085        public void writeImages(byte[] input, Set pages, Resource outputDirectory,
086                        String prefix, String format, int scale, boolean overwrite,
087                        boolean goodQuality, boolean transparent) throws PageException,
088                        IOException {
089                
090
091                File file = File.createTempFile("pdf2img", "pdf");
092                try{
093                        copy(input,file);
094                        PDFFile pdf = toPDFFile(file);
095                
096                        Resource res;
097                        int count = pdf.getNumPages();
098                         
099                        for(int page=1;page<=count;page++) {
100                                if(pages!=null && !pages.contains(Integer.valueOf(page)))continue;
101                                res=createDestinationResource(outputDirectory,prefix,page,format,overwrite);
102                                //res=outputDirectory.getRealResource(prefix+"_page_"+page+"."+format);
103                                writeImage(pdf,page,res,format,scale,overwrite,goodQuality, transparent);
104                        }
105                }
106                finally{
107                        deleteEL(file);
108                }
109        }
110        
111        private static void writeImage(PDFFile pdf, int pageNumber, Resource destination,String format, int scale,
112                        boolean overwrite, boolean goodQuality, boolean transparent) throws PageException, IOException {
113                
114                PDFPage page = pdf.getPage(pageNumber);
115                
116                if(scale<1) throw new ExpressionException("scale ["+scale+"] should be at least 1");
117                
118                int width = (int)page.getBBox().getWidth();
119                int height = (int)page.getBBox().getHeight();
120                if(scale!=100){
121                        double s=(scale)/100d;
122                        width=  (int)((width)*s);
123                        height= (int)((height)*s);
124                        
125                        
126                }
127                Image img=toImage(page, width, height,transparent);
128                img.writeOut(destination,format, overwrite, 1f);
129        }
130
131        private PDFFile toPDFFile(File file) throws IOException {
132                RandomAccessFile raf = new RandomAccessFile(file, "r");
133        FileChannel channel = raf.getChannel();
134        ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
135        return new PDFFile(buf);
136
137        }
138
139        private void deleteEL(File file) {
140                try{
141                if(!file.delete())file.deleteOnExit();
142                }
143                catch(Throwable t){
144                        ExceptionUtil.rethrowIfNecessary(t);
145                }
146        }
147
148        private void copy(byte[] input, File file) throws IOException {
149                ByteArrayInputStream bais = new ByteArrayInputStream(input);
150                FileOutputStream fos = new FileOutputStream(file);
151                IOUtil.copy(bais, fos, true,true);
152                
153        }
154
155}