package it.eng.spagobi.engines.documentcomposition.exporterUtils;
import it.eng.spagobi.commons.utilities.ExecutionProxy;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Iterator;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.log4j.Logger;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
public class PdfCreator {
Integer videoHeight;
Integer videoWidth;
float docHeight;
float docWidth;
static private Logger logger = Logger.getLogger(PdfCreator.class);
public FileOutputStream createPdfFile(FileOutputStream fileOutputStream, Map<String, DocumentContainer> documentsMap, boolean defaultStyle) throws MalformedURLException, IOException, DocumentException{
logger.debug("IN");
Document document=new Document(PageSize.A4.rotate());
Rectangle rect=document.getPageSize();
docWidth=rect.getWidth();
docHeight=rect.getHeight();
logger.debug("document size width: "+docWidth+ " height: "+docHeight);
//PdfWriter writer=PdfWriter.getInstance(document,new FileOutputStream("C:/comp/SpagoBIProva.pdf"));
PdfWriter writer=PdfWriter.getInstance(document,fileOutputStream);
document.open();
int documentsNumber=documentsMap.keySet().size();
int columnnsNumber=2;
if(defaultStyle==true){
logger.debug("use default style");
int cellsCounter=0;
PdfPTable table=new PdfPTable(columnnsNumber);
table.setWidthPercentage(100);
for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
String label = (String) iterator.next();
DocumentContainer docContainer = documentsMap.get(label);
byte[] content = docContainer.getContent();
if (content != null) {
Image img = null;
try {
img = Image.getInstance(content);
table.addCell(img);
} catch (Exception e) {
logger.debug("Trying to evaluate response as a PDF file... ");
table.addCell("");
// try {
// PdfReader reader = new PdfReader(content);
// PdfImportedPage page = writer.getImportedPage(reader, 1);
// writer.addPage(page);
// table.addCell("");
// } catch (Exception x) {
// logger.error("Error in inserting image for document " + label, e);
// logger.error("Error in inserting pdf file for document " + label, x);
// table.addCell("");
// }
}
}
cellsCounter++;
}
// if cell counter is not pair make it pair
if(cellsCounter%2!=0){
table.addCell("");
}
document.add(table);
}
else
{ // ************* NO DEFAULT STYLE *****************
logger.debug("No default style");
// I want to calculate total height of scaled heights!!
//int totalScaledHeight=calculateTotaleScaledHeights(documentsMap, defaultStyle);
// run on all documents
for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
String label = (String) iterator.next();
logger.debug("document with label "+label);
DocumentContainer docContainer= documentsMap.get(label);
MetadataStyle style=docContainer.getStyle();
// one table for each image, set at absolute position
PdfPTable table=new PdfPTable(1);
// width and height specified for the container by style attribute
int widthStyle=style.getWidth();
int heightStyle=style.getHeight();
logger.debug("style for document width: "+widthStyle+ " height: "+heightStyle);
// width and height for the table scaled to the document size
int tableWidth=calculatePxSize(docWidth, widthStyle, videoWidth);
int tableHeight=calculatePxSize(docHeight, heightStyle, videoHeight);
logger.debug("table for document width: "+tableWidth+ " height: "+tableHeight);
// x and y position as specified for the container by the style attribute
int yStyle=style.getY();
int xStyle=style.getX();
// width and height scaled to the document size
int xPos=(calculatePxPos(docWidth, xStyle, videoWidth));
int yPos=(int)docHeight-(calculatePxPos(docHeight, yStyle, videoHeight));
logger.debug("Table position at x: "+xPos+ " y: "+yPos);
// get the image
byte[] content=docContainer.getContent();
if(content != null){
Image img = null;
try {
img = Image.getInstance(content);
}
catch (Exception e) {
logger.debug("Trying to evaluate response as a PDF file... ");
try {
PdfReader reader = new PdfReader(content);
PdfContentByte cb = writer.getDirectContent();
PdfImportedPage page = writer.getImportedPage(reader, 1);
float[] tm = getTransformationMatrix(page, xPos, yPos, tableWidth, tableHeight);
cb.addTemplate(page, tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]);
} catch (Exception x) {
logger.error("Error in inserting image for document " + label, e);
logger.error("Error in inserting pdf file for document " + label, x);
}
continue;
}
//if it is a REPORT and has more than one page, too large, you have to resize the image, but how to understand it?
// if image size is more than double of the container size cut the first part,otherwise scale it
if(docContainer.getDocumentType().equals("REPORT")){
boolean cutImageWIdth=isToCutWidth(img, tableWidth);
boolean cutImageHeight=isToCutHeight(img, tableWidth);
if(cutImageWIdth==true || cutImageHeight==true){
logger.debug("Report will be cut to width "+tableWidth+" and height "+tableHeight);
try{
img=cutImage(content, cutImageHeight, cutImageWIdth, tableHeight, tableWidth, (int)img.getWidth(), (int)img.getHeight());
}catch (Exception e) {
logger.error("Error in image cut, cutt will be ignored and image will be drawn anyway ",e);
}
}
}
// this is percentage to resize
// The image must be size within the cell
int percToResize=percentageToResize((int)img.getWidth(), (int)img.getHeight(), tableWidth, tableHeight);
logger.debug("image will be scaled of percentage "+percToResize);
img.scalePercent(percToResize);
PdfPCell cell= new PdfPCell(img);
cell.setNoWrap(true);
cell.setFixedHeight(tableHeight);
cell.setBorderWidth(0);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_CENTER);
table.addCell(cell);
//table.setWidthPercentage(tableWidthPerc);
table.setTotalWidth(tableWidth);
table.setLockedWidth(true);
}
else{
// TODO: setALT!
}
logger.debug("Add table");
table.writeSelectedRows(0, -1, xPos, yPos, writer.getDirectContent());
logger.debug("Document added");
}
}
document.close();
logger.debug("OUT");
return fileOutputStream;
}
private float[] getTransformationMatrix(PdfImportedPage page, int xPos, int yPos, int tableWidth, int tableHeight) {
float pageWidth = page.getWidth();
float pageHeight = page.getHeight();
float scaleX = tableWidth/pageWidth;
float scaleY = tableHeight/pageHeight;
float scale = Math.min(scaleX, scaleY);
//float[] toReturn = {scale, 0f, 0f, scale, xPos, docHeight - tableHeight};
float dX = (float) xPos;
float dY = yPos - tableHeight;
float[] toReturn = {scale, 0f, 0f, scale, dX, dY};
return toReturn;
}
int chooseDefaultColumnsNumber(int documentsNumber){
// if(documentsNumber<=2)return documentsNumber;
// else if(documentsNumber==3 || documentsNumber==4) return 2;
// else return 3;
return 2;
}
int calculatePercentage(float documentSize, int styleSize, int videoSize){
// this is x value to object in PDF
int value=(styleSize*(int)documentSize)/videoSize;
// get percentage of x within docyment
int percentage=(value*100)/(int)documentSize;
return percentage;
}
int calculatePxSize(float documentSize, int styleSize, int videoSize){
// this is x value to object in PDF
int value=(styleSize*(int)documentSize)/videoSize;
return value;
// // get percentage of x within docyment
// int percentage=(value*100)/(int)documentSize;
// return percentage;
}
int calculatePxPos(float documentSize, int styleSize, int videoSize){
// this is x value to object in PDF
int value=(styleSize*(int)documentSize)/videoSize;
return value;
}
public Integer getVideoHeight() {
return videoHeight;
}
public void setVideoHeight(Integer videoHeight) {
this.videoHeight = videoHeight;
}
public Integer getVideoWidth() {
return videoWidth;
}
public void setVideoWidth(Integer videoWidth) {
this.videoWidth = videoWidth;
}
/**
* called only if not default style
* @param documentsMap
*/
int calculateTotalHeight(Map<String, DocumentContainer> documentsMap, boolean defaultStyle){
logger.debug("IN");
int totalHeight=0;
if(defaultStyle==false){
// total height is the maximum top+height revealed!
for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
String label = (String) iterator.next();
DocumentContainer docContainer=documentsMap.get(label);
MetadataStyle style=docContainer.getStyle();
int verticalLimit=style.getHeight()+style.getY();
if(verticalLimit>totalHeight){
totalHeight=verticalLimit;
}
}
}
logger.debug("OUT");
return totalHeight;
}
int calculateTotalWidth(Map<String, DocumentContainer> documentsMap, boolean defaultStyle){
logger.debug("IN");
int totalWidth=0;
if(defaultStyle==false){
// total height is the maximum top+height revealed!
for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
String label = (String) iterator.next();
DocumentContainer docContainer=documentsMap.get(label);
MetadataStyle style=docContainer.getStyle();
int horizontalLimit=style.getWidth()+style.getX();
if(horizontalLimit>totalWidth){
totalWidth=horizontalLimit;
}
}
}
logger.debug("OUT");
return totalWidth;
}
int calculateTotaleScaledHeights(Map<String, DocumentContainer> documentsMap, boolean defaultStyle){
logger.debug("IN");
int totalHeight=0;
if(defaultStyle==false){
// total height is the maximum top+height revealed!
for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
String label = (String) iterator.next();
DocumentContainer docContainer=documentsMap.get(label);
MetadataStyle style=docContainer.getStyle();
int height=style.getHeight()+style.getY();
int verticalLimit=calculatePxSize(docHeight, height, videoHeight);
if(verticalLimit>totalHeight){
totalHeight=verticalLimit;
}
}
}
logger.debug("OUT");
return totalHeight;
}
int percentageToResize(int imgWidth, int imgHeight, int tableWidth, int tableHeight){
logger.debug("IN");
int perc=100;
int percReductionWidth=100;
if(imgWidth>tableWidth){
percReductionWidth=(tableWidth*100)/imgWidth;
}
int percReductionHeight=100;
if(imgHeight>tableHeight){
percReductionHeight=(tableHeight*100)/imgHeight;
}
perc=percReductionHeight<percReductionWidth ? percReductionHeight : percReductionWidth;
logger.debug("OUT");
return perc;
}
// cutImage(content, cutImageHeight, cutImageWIdth, tableHeight, tableWidth);
Image cutImage(byte[] bytes, boolean cutImageHeight, boolean cutImageWidth, int tableHeight, int tableWidth, int imgWidth, int imgHeight) throws IOException, BadElementException{
logger.debug("IN");
BufferedImage image = null; // Read from a file
BufferedImage region = null;
int pxWidthToCut = (cutImageWidth==true) ? tableWidth : imgWidth;
int pxHeightToCut = (cutImageHeight==true) ? tableHeight : imgHeight;
InputStream inputStream=new ByteArrayInputStream(bytes);
image = ImageIO.read(inputStream); // Read from an input stream
try{
region = image.getSubimage(0, 0, pxWidthToCut, pxHeightToCut);
}
catch (Exception e) {
e.printStackTrace();
}
byte[] newBytes=getBytes(region);
Image cutImg = Image.getInstance(newBytes);
//ImageIO.write(region,"PNG",new File("C:/nuovaImmagine222.PNG"));
logger.debug("OUT");
return cutImg;
}
private byte[] getBytes(BufferedImage image) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", baos);
return baos.toByteArray();
}
boolean isToCutWidth(Image img, int tableWidth){
int imgWidth=(int)img.getWidth();
if(imgWidth>(4*tableWidth)) return true;
else return false;
}
boolean isToCutHeight(Image img, int tableHeight){
int imgHeight=(int)img.getHeight();
if(imgHeight>(4*tableHeight)) return true;
else return false;
}
}