I have a pdf file (obtained from a byte[] generated by iText) I need to send to a signature hardware.
Due some incompatibility with the java printer driver I can't send the PDF directly, so i need to convert it to images before. I've succeed converting each PDF page to a jpg file, but customer does not like solution cause signatures are not in all the document, only in individual pages.
As I've not found any free library, I decided to make it in four steps:
STEP1: generate PDF with itext and persist it.
FileOutputStream fos = new FileOutputStream("tempFile.pdf");
fos.write(myByteArray);
fos.close();
fos.flush();
STEP 2: convert from PDF multipaged to List<java.awt.Image>
List<Image> images = null;
Ghostscript.getInstance(); // create gs instance
PDFDocument lDocument = new PDFDocument();
lDocument.load(new File("tempFile.pdf"));
SimpleRenderer renderer = new SimpleRenderer();
renderer.setResolution(300);
try
{
images = renderer.render(lDocument);
}
catch (RendererException | DocumentException e)
{
e.printStackTrace();
}
Step 3: Now I iterate over List<java.awt.Image> to convert to an individual TIFF's.
int filename = 1;
TIFFEncodeParam params = new TIFFEncodeParam();
Iterator<Image> imageIterator = images.iterator();
while (imageIterator.hasNext()) {
BufferedImage image = (BufferedImage) imageIterator.next();
FileOutputStream os = new FileOutputStream(/*outputDir + */ filename + ".tif");
JAI.create("encode", image , os, "TIFF", params);
filename ++;
}
STEP 4: create multipaged TIFF from various individual TIFF files
BufferedImage image[] = new BufferedImage[paginas];
for (int i = 0; i < paginas; i++) {
SeekableStream ss = new FileSeekableStream((i + 1) + ".tif");
ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);
PlanarImage pi = new NullOpImage(decoder.decodeAsRenderedImage(0),null,null,OpImage.OP_IO_BOUND);
image[i] = pi.getAsBufferedImage();
ss.close();
}
TIFFEncodeParam params = new TIFFEncodeParam();
params.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
OutputStream out = new FileOutputStream(nombre +".tif");
ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
List <BufferedImage>list = new ArrayList<BufferedImage>(image.length);
for (int i = 1; i < image.length; i++) {
list.add(image[i]);
}
params.setExtraImages(list.iterator());
encoder.encode(image[0]);
out.close();
System.out.println("Done.");
DONE. Hope that helps for someone else with same problem.
I had same issue a while ago. I got lot of help from here:
Multiple page tif
Allso check:
JAI (Java Advance Image)
Here is the conde snippet to convert pdf pages to png images (using org.apache.pdfbox library):
PDDocument document = null;
document = PDDocument.load(pdf1);
int pageNum = document.getNumberOfPages();
PDFImageWriter writer = new PDFImageWriter();
String filename = pdf1.getPath() + "-";
filename = filename.replace(".pdf", "");
writer.writeImage(document, "png", "", 1, Integer.MAX_VALUE, filename);
document.close();
And after that i converted each PNG image to TIFF and then from multiple TIFF images to single multi paged TIFF.
Related
I am experiencing an EOF Exception as follows when attempting to read tiff files using iText 5.5.10
ExceptionConverter: java.io.EOFException
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:249)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:241)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:209)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:314)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:302)
at com.itextpdf.text.Image.getInstance(Image.java:428)
at com.itextpdf.text.Image.getInstance(Image.java:374)
at TiffToPdf.main(TiffToPdf.java:137)
The code I am using is:
byte[] data = null;
Image img = null;
try {
data = Files.readAllBytes(Paths.get("tiff.tif"));
img = Image.getInstance(data, true);
}
catch (Exception e) {
e.printStackTrace();
}
I have tried skipping the Image step and using the TiffImage class explicitly but I experience the same error.
byte[] data = null;
Image img = null;
try {
data = Files.readAllBytes(Paths.get("tiff.tif"));
RandomAccessSourceFactory factory = new RandomAccessSourceFactory();
RandomAccessSource fileBytes = factory.createSource(data);
RandomAccessFileOrArray s = new RandomAccessFileOrArray(fileBytes);
img = TiffImage.getTiffImage(s, true, 1, true);
}
catch (Exception e) {
e.printStackTrace();
}
I noticed that there are 2 classes within iText called TIFFFaxDecompressor and TIFFFaxDecoder but I haven't been able to find any resources online on how to use them.
with your given tiff image, the following code does worked for me i.e., converted to pdf successfully.
byte[] data = null;
com.itextpdf.text.Image img = null;
try {
//System.out.println(Paths.get("src/main/resources/tiff.tif"));
data = Files.readAllBytes(Paths.get("src/main/resources/file.tif"));
RandomAccessSourceFactory factory = new RandomAccessSourceFactory();
RandomAccessSource fileBytes = factory.createSource(data);
RandomAccessFileOrArray s = new RandomAccessFileOrArray(fileBytes);
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("src/main/resources/destination.pdf"));
document.open();
int pages = TiffImage.getNumberOfPages(s);
Image image;
for (int i = 1; i <= pages; i++) {
image = TiffImage.getTiffImage(s, i);
Rectangle pageSize = new Rectangle(image.getWidth(),
image.getHeight());
document.setPageSize(pageSize);
document.newPage();
document.add(image);
}
document.close();
} catch (Exception e) {
e.printStackTrace();
}
I'm searching a method with JRGraphics2DExporter to export report as JPG.
Is there any kind of possibility to do that with JRGraphics2DExporter?
You want to use the JRGraphics2DExporter, but this can also be done directly using the JasperPrintManager
Example of code contemplenting multiple images 1 for every page
//Get my print, by filling the report
JasperPrint jasperPrint = JasperFillManager.fillReport(report, map,datasource);
final String extension = "jpg";
final float zoom = 1f;
String fileName = "report";
//one image for every page in my report
int pages = jasperPrint.getPages().size();
for (int i = 0; i < pages; i++) {
try(OutputStream out = new FileOutputStream(fileName + "_p" + (i+1) + "." + extension)){
BufferedImage image = (BufferedImage) JasperPrintManager.printPageToImage(jasperPrint, i,zoom);
ImageIO.write(image, extension, out); //write image to file
} catch (IOException e) {
e.printStackTrace();
}
}
If you like 1 image with all the pages, you should set the isIgnorePagination="true" on the jasperReport tag
You could instruct to the exporter in order to dump the report to an image in memory and then save it to disk.
Create the image (set the proper width, height and format):
BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);
Create the exporter, configure it (maybe some other parameters should be set) and export the report:
JRGraphics2DExporter exporter = new JRGraphics2DExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRGraphics2DExporterParameter.GRAPHICS_2D, (Graphics2D)image.getGraphics());
exporter.setParameter(JRGraphics2DExporterParameter.ZOOM_RATIO, Float.valueOf(1));
exporter.exportReport();
Dump the image to disk:
ImageIO.write(image, "PNG", new File("image.png"));
i'm using iText 5.5.5 with Java5.
I'm trying to merge some PDF/A. when I got a "PdfAConformanceException: PDF array is out of bounds".
Trying to find error I find the "bad PDF" that cause the error and when I try to copy just it exception throw again. This error don't appear always, it appear just when this PDF/A is in the "job chain"; I tried with some other files and it's all fine. I cant share with you source PDF 'couse it's restricted.
That's my piece of code:
_log.info("Start Document Merge");
// Output pdf
ByteArrayOutputStream bos = new ByteArrayOutputStream();
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfCopy copy = new PdfACopy(document, bos, PdfAConformanceLevel.PDF_A_1B);
PageStamp stamp = null;
PdfReader reader = null;
PdfContentByte content = null;
int outPdfPageCount = 0;
BaseFont baseFont = BaseFont.createFont("Arial", BaseFont.WINANSI, BaseFont.EMBEDDED);
copyOutputIntents(reader, copy);
// Loop over the pages in that document
try {
int numberOfPages = reader.getNumberOfPages();
for (int i = 1; i <= numberOfPages; i++) {
PdfImportedPage pagecontent = copy.getImportedPage(reader, i);
_log.debug("Handling page numbering [" + i + "]");
stamp = copy.createPageStamp(pagecontent);
content = stamp.getUnderContent();
content.beginText();
content.setFontAndSize(baseFont, Configuration.NumPagSize);
content.showTextAligned(PdfContentByte.ALIGN_CENTER, String.format("%s %s ", Configuration.NumPagPrefix, i), Configuration.NumPagX, Configuration.NumPagY, 0);
content.endText();
stamp.alterContents();
copy.addPage(pagecontent);
outPdfPageCount++;
if (outPdfPageCount > Configuration.MaxPages) {
_log.error("Pdf Page Count > MaxPages");
throw new PackageException(Constants.ERROR_104_TEXT, Constants.ERROR_104);
}
}
copy.freeReader(reader);
reader.close();
copy.createXmpMetadata();
document.close();
} catch (Exception e) {
_log.error("Error during mergin Document, skip");
_log.debug(MiscUtil.stackToString(e));
}
return bos.toByteArray();
That's the full stacktrace:
com.itextpdf.text.pdf.PdfAConformanceException: PDF array is out of bounds.
at com.itextpdf.text.pdf.internal.PdfA1Checker.checkPdfObject(PdfA1Checker.java:269)
at com.itextpdf.text.pdf.internal.PdfAChecker.checkPdfAConformance(PdfAChecker.java:208)
at com.itextpdf.text.pdf.internal.PdfAConformanceImp.checkPdfIsoConformance(PdfAConformanceImp.java:71)
at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3480)
at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3476)
at com.itextpdf.text.pdf.PdfArray.toPdf(PdfArray.java:165)
at com.itextpdf.text.pdf.PdfDictionary.toPdf(PdfDictionary.java:149)
at com.itextpdf.text.pdf.PdfArray.toPdf(PdfArray.java:175)
at com.itextpdf.text.pdf.PdfDictionary.toPdf(PdfDictionary.java:149)
at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:158)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:420)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:398)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:373)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:369)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:843)
at com.itextpdf.text.pdf.PdfCopy.addToBody(PdfCopy.java:839)
at com.itextpdf.text.pdf.PdfCopy.addToBody(PdfCopy.java:821)
at com.itextpdf.text.pdf.PdfCopy.copyIndirect(PdfCopy.java:426)
at com.itextpdf.text.pdf.PdfCopy.copyIndirect(PdfCopy.java:446)
at com.itextpdf.text.pdf.PdfCopy.copyObject(PdfCopy.java:577)
at com.itextpdf.text.pdf.PdfCopy.copyDictionary(PdfCopy.java:503)
at com.itextpdf.text.pdf.PdfCopy.copyObject(PdfCopy.java:573)
at com.itextpdf.text.pdf.PdfCopy.copyDictionary(PdfCopy.java:503)
at com.itextpdf.text.pdf.PdfCopy.copyObject(PdfCopy.java:573)
at com.itextpdf.text.pdf.PdfCopy.copyDictionary(PdfCopy.java:493)
at com.itextpdf.text.pdf.PdfCopy.copyDictionary(PdfCopy.java:519)
at com.itextpdf.text.pdf.PdfCopy.addPage(PdfCopy.java:663)
at com.itextpdf.text.pdf.PdfACopy.addPage(PdfACopy.java:115)
at it.m2sc.engageone.documentpackage.generator.PackageGenerator.mergePDF(PackageGenerator.java:256)
In that specific case, the problem depends by a specific Font ( Gulim ) that is too big to be embedded in PDF/A-1 file. When that font was removed, everything war run fine.
I'm getting heap space error/ out of memory exception.
I'm trying to generate a PDF using iText and converting the PDF to jpg image using aspose api. The PDF which is being generated is of 3 pages, I'm converting that PDF to image page by page and stitching them together into one jpg image. This code is working fine in my local development machine, but getting exception when move to test server.
The code which I'm using for this is:
public void silSignedPDF(AgreementBean agBean,String sourceTemplatePDFURL, Hashtable<String, String> val, String destinationPDFPath) throws IOException, DocumentException, SQLException{
String methodName = "silSignedPDF";
LogTracer.writeDebugLog(className, methodName, "Start");
String serverPath = System.getProperty("jboss.server.home.dir");
String sourceTemplatePDFURL1 = serverPath+AppConstants.PDL_Agreement_Template +"/Online_Installment_Agreement.pdf";
System.out.println("sourceTemplatePDFURL1 "+sourceTemplatePDFURL1);
File f = new File(sourceTemplatePDFURL1);
InputStream sourceTemplatePDFUrlStream = new BufferedInputStream(new FileInputStream(f));
File destinationFile = new File(destinationPDFPath+"/"+agBean.getDealNbr()+".pdf");
PdfReader reader = new PdfReader(sourceTemplatePDFUrlStream);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
destinationFile));
AcroFields form = stamper.getAcroFields();
Enumeration enumeration = val.keys();
// iterate through Hashtable val keys Enumeration
while (enumeration.hasMoreElements()) {
String nextElement = (String) enumeration.nextElement();
String nextElementValue = (String) val.get(nextElement);
form.setField(nextElement, nextElementValue);
}
stamper.setFormFlattening(true);
stamper.close();
PdfConverter pdf = new PdfConverter();
pdf.bindPdf(destinationPDFPath+"/"+agBean.getDealNbr()+".pdf");
try {
pdf.doConvert();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//set start and end pages
pdf.setStartPage(1);
pdf.setEndPage(1);
//initialize conversion process
//convert pages to images
String suffix = ".jpg";
int imageCount = 1;
while (pdf.hasNextImage())
{
try {
pdf.getNextImage(destinationPDFPath+"/"+agBean.getDealNbr()+"_"+imageCount + suffix,ImageType.JPEG);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
imageCount++;
}
/* PDFImages pdfDoc = new PDFImages (destinationPDFPath+"/"+agBean.getDealNbr()+".pdf", null);
for (int count = 0; count < pdfDoc.getPageCount(); ++count)
{
pdfDoc.savePageAsJPEG(count,destinationPDFPath+"/"+agBean.getDealNbr()+"_"+count + ".png", 150, 0.8f);
}*/
File file1 = new File(destinationPDFPath+"/"+agBean.getDealNbr()+"_1" + ".jpg");
File file2 = new File(destinationPDFPath+"/"+agBean.getDealNbr()+"_2" + ".jpg");
File file3 = new File(destinationPDFPath+"/"+agBean.getDealNbr()+"_3" + ".jpg");
BufferedImage img1 = ImageIO.read(file1);
BufferedImage img2 = ImageIO.read(file2);
BufferedImage img3 = ImageIO.read(file3);
int widthImg1 = img1.getWidth();
int heightImg1 = img1.getHeight();
int heightImg2 = img2.getHeight();
int heightImg3 = img3.getHeight();
BufferedImage img = new BufferedImage(
widthImg1,
heightImg1+heightImg2+heightImg3,
BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(img1, 0, 0, null);
img.createGraphics().drawImage(img2, 0, heightImg1, null);
img.createGraphics().drawImage(img3, 0, heightImg1+heightImg2, null);
File final_image = new File(destinationPDFPath+"/"+agBean.getDealNbr() + ".jpg");
ImageIO.write(img, "png", final_image);
file1.delete();
file2.delete();
file3.delete();
LogTracer.writeDebugLog(className, methodName, "End");
}
Heap size should be changed for your JVM, but dont change it to any random number. Heap size should be modified based on the memory that is used by your system. You can check this for further specification.
Page to Image conversion using Aspose.Pdf required more memory than the default. Run the program with at least 512 MB memory (-Xmx512m).
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileOutputStream(outFile));
document.open();
PdfImportedPage page = writer.getImportedPage(reader, ++i);
writer.setFullCompression();
writer.addPage(page);
document.close();
writer.close();
I am using iText to split and merger the PDF, I need your help to reduce (compress) the output PDF size programmatically. Please let me know the steps to achieve the same.
use iText
PdfReader reader = new PdfReader(new FileInputStream("input.pdf"));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("output.pdf"));
int total = reader.getNumberOfPages() + 1;
for ( int i=1; i<total; i++) {
reader.setPageContent(i + 1, reader.getPageContent(i + 1));
}
stamper.setFullCompression();
stamper.close();
With writer.setFullCompression() you already compressed file as much as possible. With iText you can't do anything more.
Also change the PdfCopy to PdfSmartCopy. It will eliminate duplicate streams which have the same hash (md5).
You can use ghostscript, invoking the exe with specific parameters for print your pdf with the ghostscript's pdfwriter (example: sDEVICE=pdfwrite -sOutputFile=myfile.pdf). There are several accepted parameters, for compression or quality levels, etc.
It may result and optimized and smaller file.
Multiple Bitmap Image to pdf converter --> Compressed Pdf
public static String createPDFWithMultipleImage(Bitmap[] bitmaps, String pdf_name){
String directoryPath = Environment.getExternalStorageDirectory() + "/OpPath/";
File file = new File(directoryPath,pdf_name);
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfDocument pdfDocument = new PdfDocument();
for (int i = 0; i < bitmaps.length; i++){
Bitmap original = bitmaps[i];
int nh = (int) ( original.getHeight() * (512.0 / original.getWidth()) );
Bitmap bitmap = Bitmap.createScaledBitmap(original, 512, nh, true);
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), (i + 1)).create();
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawPaint(paint);
canvas.drawBitmap(bitmap, 0f, 0f, null);
pdfDocument.finishPage(page);
bitmap.recycle();
}
pdfDocument.writeTo(fileOutputStream);
pdfDocument.close();
return file.toString();
} catch (IOException e) {
e.printStackTrace();
return file.toString();
}
}