package org.jpedal.examples.images;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import javax.imageio.ImageIO;
import org.jpedal.PdfDecoder;
import org.jpedal.color.ColorSpaces;
import org.jpedal.exception.PdfException;
import org.jpedal.utils.LogWriter;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.io.JAIHelper;
import org.jpedal.constants.JPedalSettings;
import org.jpedal.constants.PageInfo;
public class HiResThumbnailExtractor {
private static boolean debug = false;
PdfDecoder decoder = new PdfDecoder(true);
/**correct separator for OS */
final static String separator = System.getProperty( "file.separator" );
//only used if between 0 and 1
private float JPEGcompression=-1f;
public HiResThumbnailExtractor() {}
public static void main(String[] args) throws Exception {
/*
* Change these variables
*/
String fileType="";
String pdfFile="";
if(args!=null && args.length>1){
pdfFile = args[0];
fileType= args[1];
if(pdfFile.toLowerCase().endsWith(".pdf") && (fileType.equals("jpg") || fileType.equals("jpeg") || fileType.equals("png") || fileType.equals("tiff") || fileType.equals("tif"))){
new HiResThumbnailExtractor(fileType, pdfFile);
}else{
File testDir=new File(pdfFile);
if(testDir.isDirectory()){
/**
* get list of files and check directory
*/
String[] files = null;
File inputFiles = null;
/**make sure name ends with a deliminator for correct path later*/
if (!pdfFile.endsWith(separator))
pdfFile = pdfFile + separator;
try {
inputFiles = new File(pdfFile);
files = inputFiles.list();
} catch (Exception ee) {
LogWriter.writeLog("Exception trying to access file " + ee.getMessage());
}
/**now work through all pdf files*/
long fileCount = files.length;
for (int i = 0; i < fileCount; i++) {
if (files[i].toLowerCase().endsWith(".pdf"))
new HiResThumbnailExtractor(fileType,pdfFile + files[i]);
}
}else
System.out.println("The file to be processed has to be a pdf and the output filetype can only be jpg,png or tiff");
}
}else{
System.out.println("Not enough arguments passed in! Usage: \"C:\\examples\\1.pdf\" \"jpg\"");
}
}
HiResThumbnailExtractor(String fileType, String pdfFile) throws Exception {
long startTime=System.currentTimeMillis();
String outputPath = pdfFile.substring(0, pdfFile.toLowerCase().indexOf(".pdf")) + separator;
File outputPathFile = new File(outputPath);
if (!outputPathFile.exists() || !outputPathFile.isDirectory()) {
if (!outputPathFile.mkdirs()) {
if(debug)
System.err.println("Can't create directory " + outputPath);
}
}
final PdfDecoder decoder = new PdfDecoder(true);
//mappings for non-embedded fonts to use
PdfDecoder.setFontReplacements(decoder);
decoder.openPdfFile(pdfFile);
Map mapValues = new HashMap();
/** USEFUL OPTIONS*/
//do not scale above this figure
mapValues.put(JPedalSettings.EXTRACT_AT_BEST_QUALITY_MAXSCALING, new Integer(2));
//alternatively secify a page size (aspect ratio preserved so will do best fit)
//set a page size (JPedal will put best fit to this)
mapValues.put(JPedalSettings.EXTRACT_AT_PAGE_SIZE, new String[]{"2000","1600"});
//which takes priority (default is false)
mapValues.put(JPedalSettings.PAGE_SIZE_OVERRIDES_IMAGE, Boolean.TRUE);
/**/
/** used to debug issue
mapValues.clear();
mapValues.put(JPedalSettings.EXTRACT_AT_PAGE_SIZE,new String[]{"2000","1600"});
mapValues.put(JPedalSettings.IMAGE_HIRES,Boolean.TRUE);
mapValues.put(JPedalSettings.IGNORE_FORMS_ON_PRINT,new int[]{1,2});
/**/
PdfDecoder.modifyJPedalParameters(mapValues);
if(debug)
System.out.println("pdf : " + pdfFile);
try{
/**
* allow output to multiple images with different values on each
*
* Note we REMOVE shapes as it is a new feature and we do not want to break existing functions
*/
String separation=System.getProperty("org.jpedal.separation");
if(separation!=null){
Object[] sepValues=new Object[]{new Integer(7),"",Boolean.FALSE}; //default of normal
if(separation.equals("all")){
sepValues=new Object[]{new Integer(PdfDecoder.RENDERIMAGES),"image_and_shapes",Boolean.FALSE,
new Integer(PdfDecoder.RENDERIMAGES+PdfDecoder.REMOVE_RENDERSHAPES),"image_without_shapes",Boolean.FALSE,
new Integer(PdfDecoder.RENDERTEXT),"text_and_shapes",Boolean.TRUE,
new Integer(7),"all",Boolean.FALSE,
new Integer(PdfDecoder.RENDERTEXT+PdfDecoder.REMOVE_RENDERSHAPES),"text_without_shapes",Boolean.TRUE
};
}
int sepCount =sepValues.length;
for(int seps=0;seps<sepCount;seps=seps+3){
decoder.setRenderMode(((Integer)sepValues[seps]).intValue());
extractPageAsImage(fileType, outputPath, decoder,"_"+sepValues[seps+1],((Boolean)sepValues[seps+2]).booleanValue()); //boolean makes last transparent so we can see white text
}
}else //just get the page
extractPageAsImage(fileType, outputPath, decoder,"",false);
} finally {
decoder.closePdfFile();
}
System.out.println("time="+(System.currentTimeMillis()-startTime)/1000);
}
private void extractPageAsImage(String fileType, String outputPath, PdfDecoder decoder, String prefix, boolean isTransparent) throws PdfException, IOException {
int start=1, end=decoder.getPageCount();
BufferedImage[] multiPages = new BufferedImage[1 + (end-start)];
String multiPageFlag=System.getProperty("org.jpedal.multipage_tiff");
boolean isSingleOutputFile=multiPageFlag!=null && multiPageFlag.toLowerCase().equals("true");
//allow user to specify value
String rawJPEGComp=System.getProperty("org.jpedal.compression_jpeg");
if(rawJPEGComp!=null){
try{
JPEGcompression=Float.parseFloat(rawJPEGComp);
}catch(Exception e){
e.printStackTrace();
}
if(JPEGcompression<0 || JPEGcompression>1)
throw new RuntimeException("Invalid value for JPEG compression - must be between 0 and 1");
}
String tiffFlag=System.getProperty("org.jpedal.compress_tiff");
String jpgFlag=System.getProperty("org.jpedal.jpeg_dpi");
boolean compressTiffs = tiffFlag!=null && tiffFlag.toLowerCase().equals("true");
for (int pageNo = start; pageNo < end+1; pageNo++) {
if(debug)
System.out.println("page : " + pageNo);
/**
* example1 - ask JPedal to return from decoding if file takes too long (time is in millis)
* will reset after exit so call for each page
*/
//decoder.setPageDecodeStatus(DecodeStatus.Timeout,new Integer(20) );
/**
* example2 thread which will ask JPedal to time out and return from decoding
* will reset after exit so call for each page
*/
/**
Thread a=new Thread(){
public void run() {
while(true){
//simulate 2 second delay
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
//tell JPedal to exit asap
decoder.setPageDecodeStatus(DecodeStatus.Timeout, Boolean.TRUE);
}
}
};
//simulate a second thread
a.start();
//see code after line decoder.getPageAsHiRes(pageNo); for tracking whether JPedal timed out and returned
/**/
/**
* If you are using decoder.getPageAsHiRes() after passing additional parameters into JPedal using the static method
* PdfDecoder.modifyJPedalParameters(), then getPageAsHiRes() wont necessarily be thread safe. If you want to use
* getPageAsHiRes() and pass in additional parameters, in a thread safe mannor, please use the method
* getPageAsHiRes(int pageIndex, Map params) or getPageAsHiRes(int pageIndex, Map params, boolean isTransparent) and
* pass the additional parameters in directly to the getPageAsHiRes() method without calling PdfDecoder.modifyJPedalParameters()
* first.
*
* Please see http://www.jpedal.org/support_egHiRes.php for more details on how to use HiResThumbnailExtraction.
*/
BufferedImage imageToSave = decoder.getPageAsHiRes(pageNo,null,isTransparent);
//show status flag
/**
if(decoder.getPageDecodeStatus(DecodeStatus.Timeout))
System.out.println("Timeout on decoding");
else
System.out.println("Done");
/**/
decoder.flushObjectValues(true);
//System.out.println("w="+imageToSave.getWidth()+" h="+imageToSave.getHeight());
//image needs to be sRGB for JPEG
if(fileType.equals("jpg"))
imageToSave = ColorSpaceConvertor.convertToRGB(imageToSave);
String outputFileName="";
if(isSingleOutputFile)
outputFileName = outputPath+ "allPages"+prefix+"." + fileType;
else
outputFileName = outputPath + "page" + pageNo +prefix + "." + fileType;
File file = new File(outputFileName);
//if just gray we can reduce memory usage by converting image to Grayscale
/**
* see what Colorspaces used and reduce image if appropriate
* (only does Gray at present)
*
* Can return null value if not sure
*/
Iterator colorspacesUsed=decoder.getPageInfo(PageInfo.COLORSPACES);
int nextID;
boolean isGrayOnly=colorspacesUsed!=null; //assume true and disprove
while(colorspacesUsed!=null && colorspacesUsed.hasNext()){
nextID=((Integer)(colorspacesUsed.next())).intValue();
if(nextID!= ColorSpaces.DeviceGray && nextID!=ColorSpaces.CalGray)
isGrayOnly=false;
}
//draw onto GRAY image to reduce colour depth
//(converts ARGB to gray)
if(isGrayOnly){
BufferedImage image_to_save2=new BufferedImage(imageToSave.getWidth(),imageToSave.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
image_to_save2.getGraphics().drawImage(imageToSave,0,0,null);
imageToSave = image_to_save2;
}
//put image in array if multi-images
if(isSingleOutputFile)
multiPages[pageNo-start] = imageToSave;
if (imageToSave != null) {
/**BufferedImage does not support any dpi concept. A higher dpi can be created
* using JAI to convert to a higher dpi image*/
//shrink the page to 50% with graphics2D transformation
//- add your own parameters as needed
//you may want to replace null with a hints object if you
//want to fine tune quality.
/** example 1 biliniear scaling
AffineTransform scale = new AffineTransform();
scale.scale(.5, .5); //50% as a decimal
AffineTransformOp scalingOp =new AffineTransformOp(scale, null);
image_to_save =scalingOp.filter(image_to_save, null);
*/
if(JAIHelper.isJAIused())
JAIHelper.confirmJAIOnClasspath();
if(JAIHelper.isJAIused() && fileType.startsWith("tif")){
com.sun.media.jai.codec.TIFFEncodeParam params = new com.sun.media.jai.codec.TIFFEncodeParam();
if(compressTiffs)
params.setCompression(com.sun.media.jai.codec.TIFFEncodeParam.COMPRESSION_PACKBITS);
if(!isSingleOutputFile){
FileOutputStream os = new FileOutputStream(outputFileName);
javax.media.jai.JAI.create("encode", imageToSave, os, "TIFF", params);
}else if(isSingleOutputFile && pageNo == end){
OutputStream out = new FileOutputStream(outputFileName);
com.sun.media.jai.codec.ImageEncoder encoder = com.sun.media.jai.codec.ImageCodec.createImageEncoder("TIFF", out, params);
Vector vector = new Vector();
vector.addAll(Arrays.asList(multiPages).subList(1, multiPages.length));
params.setExtraImages(vector.iterator());
encoder.encode(multiPages[0]);
out.close();
}
}else if(isSingleOutputFile){
//non-JAI
} else if ((jpgFlag != null || rawJPEGComp!=null) && fileType.startsWith("jp") && JAIHelper.isJAIused()) {
com.sun.image.codec.jpeg.JPEGImageEncoder jpegEncoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(new FileOutputStream(outputFileName));
com.sun.image.codec.jpeg.JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(imageToSave);
if (jpgFlag != null){
int dpi = 96;
try {
dpi = Integer.parseInt(jpgFlag);
} catch (Exception e) {
e.printStackTrace();
}
jpegEncodeParam.setDensityUnit(com.sun.image.codec.jpeg.JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
jpegEncodeParam.setXDensity(dpi);
jpegEncodeParam.setYDensity(dpi);
}
if(JPEGcompression>=0 && JPEGcompression<=1f){
jpegEncodeParam.setQuality(JPEGcompression,false);
System.out.println("xx");
}
jpegEncoder.encode(imageToSave, jpegEncodeParam);
} else {
ImageIO.write(imageToSave,fileType,file);
}
//if you just want to save the image, use something like
//javax.imageio.ImageIO.write((java.awt.image.RenderedImage)image_to_save,"png",new java.io.FileOutputStream(output_dir + page + image_name+".png"));
}
imageToSave.flush();
imageToSave=null;
if(debug){
System.out.println("Created : " + outputFileName);
}
}
}
}
|