/*
* Copyright (C) 2006-2014 Gabriel Burca (gburca dash virtmus at ebixio dot com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.ebixio.virtmus.imgsrc;
import com.ebixio.util.Log;
import com.ebixio.virtmus.Utils;
import com.sun.pdfview.PDFCmd;
import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFObject;
import com.sun.pdfview.PDFPage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RenderedOp;
import org.openide.util.Exceptions;
/**
* A class that uses com.sun.pdfview to rasterize PDFs.
* @author Gabriel Burca <gburca dash virtmus at ebixio dot com>
*/
@XStreamAlias("pdfImg")
public class PdfViewImg extends PdfImg {
public PdfViewImg(File sourceFile, int pageNum) {
super(sourceFile, pageNum);
}
@Override
public Dimension getDimension() {
PDFPage pdfPage = getPdfPage(null);
Dimension dim = getLargestDisplay();
int max = Math.max(dim.width, dim.height);
Dimension pdim = pdfPage.getUnstretchedSize(max, max, null);
int min = Math.min(pdim.width, pdim.height);
float pageScale = (max * 1F) / min;
return new Dimension((int)(pdim.width * pageScale), (int)(pdim.height * pageScale));
// TODO: The new version of PDFRenderer doesn't have getPageImages().
// int rotation = pdfPage.getRotation();
// List<PDFImage> imgs = pdfPage.getPageImages();
// if (imgs.size() == 1) {
// PDFImage img = imgs.get(0);
// if (rotation == 90 || rotation == 270) {
// return new Dimension(img.getHeight(), img.getWidth());
// } else {
// return new Dimension(img.getWidth(), img.getHeight());
// }
// }
}
private void debug() {
final PDFFile pdfFile = getPDFFile();
try {
Iterable<String> kIt = new Iterable<String>() {
@Override
public Iterator<String> iterator() {
try { return pdfFile.getMetadataKeys();
} catch (IOException ex) { return null; }
}
};
for (String k : kIt) {
Log.log("Key: " + k + " = " + pdfFile.getStringMetadata(k));
}
PDFObject root = pdfFile.getRoot();
for (String k : root.getDictionary().keySet()) {
Log.log("RootDictKey: " + k);
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
PDFPage pdfPage = getPdfPage(pdfFile);
for (PDFCmd cmd : pdfPage.getCommands()) {
Log.log("CmdClass: " + cmd.getClass().getCanonicalName());
Log.log("Cmd: " + cmd.toString() + " Details: " + cmd.getDetails());
}
}
/** Find the largest display the page might need to be rendered for. */
private Dimension getLargestDisplay() {
Dimension[] dims = Utils.getScreenSizes();
int biggest = -1, idx = -1;
for (int i = 0; i < dims.length; i++) {
if (dims[i].width * dims[i].height > biggest) {
biggest = dims[i].width * dims[i].height;
idx = i;
}
}
Dimension dim = dims[idx];
return dim;
}
@Override
public PlanarImage getFullImg() {
RenderedOp op = getFullRenderedOp();
if (op == null) {
return null;
} else {
return PlanarImage.wrapRenderedImage(op);
}
}
@Override
protected RenderedOp getFullRenderedOp() {
Image img = getPageImage();
if (img == null) {
return null;
} else {
RenderedOp rend = JAI.create("AWTImage", img);
return rend;
}
}
private Image getPageImage() {
debug();
PDFPage pdfPage = getPdfPage(null);
if (pdfPage == null) return null;
Dimension dim = getDimension();
/*
Note: The crop box is in PDF coordinate space with the y-axis increasing
going up. PDF origin is at the bottom left of the page. Java origin is
at the top left of the screen.
*/
Rectangle2D cbox = pdfPage.getPageBox();
Rectangle2D bbox = pdfPage.getBBox();
Image img = pdfPage.getImage(
dim.width, dim.height,
cbox, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true); // block until drawing is done
return img;
}
private PDFPage getPdfPage(PDFFile pdfFile) {
if (pdfFile == null) {
pdfFile = getPDFFile();
}
if (pdfFile != null) {
return pdfFile.getPage(getPageNum() + 1, true);
} else {
return null;
}
}
private PDFFile getPDFFile() {
try {
RandomAccessFile raf = new RandomAccessFile(sourceFile, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdfFile = new PDFFile(buf);
return pdfFile;
} catch (FileNotFoundException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return null;
}
@Override
public File createImageFile() {
tmpImgFile = null;
try {
tmpImgFile = File.createTempFile("VirtMus", ".jpg");
ImageIO.write(getFullRenderedOp(), "jpg", tmpImgFile);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return tmpImgFile;
}
}