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();
}
}
Related
I'm working on PDF related project and I want to create a PDF from the existing PDF.
all things are done but when I created a final PDF at that time this exception was thrown at the line of document.close(); at the method of savePDF which describe below.
Create new PDF from existing PDF adding PdfImportedPage.
here is my code
The app crashes only when we add a new page
private void createAndAddPage(Bitmap bitmap) {
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Document document = new Document();
File file = getPdfFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOutputStream); // Change pdf's name.
document.open();
Image image = Image.getInstance(byteArray); // Change image's name and extension.
float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
- document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
image.scalePercent(scaler);
image.setAlignment(Image.ALIGN_CENTER);
document.add(image);
document.close();
PdfReader pdfReader = new PdfReader(file.getPath());
PdfImportedPage pdfImportedPage = pdfWriter.getImportedPage(pdfReader, 1);
pageAdjustmentAdapter.AddPage(new PageAjdustAdapter.PdfPage(pdfImportedPage, bitmap));
} catch (Exception e) {
e.printStackTrace();
}
}
method when saves a final PDF(crash happens in this method)
private void savePDF(PageAjdustAdapter pageAdjustment) {
mPDFpages = pageAdjustment.getUpdatedList();
try {
pdfWriter.setPageEvent(new RotateEvent());
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (int i = 0; i < mPDFpages.size(); i++) {
pdfContentByte.addTemplate(mPDFpages.get(i).page, 0, 0);
document.newPage();
}
} catch (Exception e) {
Log.d(TAG, "run: -> " + e.getMessage());
e.printStackTrace();
} finally {
if (document.isOpen()) document.close();
actionListener.onEnd("Success");
}
}
logcat
ExceptionConverter: java.io.IOException: Stream Closed
at java.io.FileOutputStream.write(FileOutputStream.java:391)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:121)
at java.io.FilterOutputStream.write(FilterOutputStream.java:103)
at com.itextpdf.text.pdf.OutputStreamCounter.write(OutputStreamCounter.java:104)
at com.itextpdf.text.pdf.PRStream.toPdf(PRStream.java:244)
at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:157)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:402)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:380)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:359)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:854)
at com.itextpdf.text.pdf.PdfReaderInstance.writeAllVisited(PdfReaderInstance.java:160)
at com.itextpdf.text.pdf.PdfReaderInstance.writeAllPages(PdfReaderInstance.java:176)
at com.itextpdf.text.pdf.PdfWriter.addSharedObjectsToBody(PdfWriter.java:1368)
at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1251)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:901)
at com.itextpdf.text.Document.close(Document.java:415)
at com.mobilix.docscanner.PageAdjustment$8.run(PageAdjustment.java:233)
at java.lang.Thread.run(Thread.java:923)
In createAndAddPage you import the page into the wrong PdfWriter:
Document document = new Document();
File file = getPdfFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOutputStream); // Change pdf's name.
document.open();
[...]
document.close();
PdfReader pdfReader = new PdfReader(file.getPath());
PdfImportedPage pdfImportedPage = pdfWriter.getImportedPage(pdfReader, 1);
Here you import the new page into the PdfWriter used for creating that same new page. You instead have to import it into the PdfWriter in which you eventually want to use the pdfImportedPage.
I'm using itext5 to scale down pdf document, however i notice that the rotation information is rarely used in pdf documents metadata, it's still possible to find out the orientation by checking the width and the height of the page but with the following pdf document i end up with a pdf that has both pages in landscape orientation and in portrait orientation however all the pages are rendered in the same orientation (in the common pdf viewers).
My question is where is that information stored ? How the pdf viewer is able to render the document as it should ?
This the orignal pdf file
This is the metadata i'm able to retrieve
This is the method used :
Document document = new Document(MarginsPDFHelper.DIM_PAGE, MarginsPDFHelper.MARGIN_GEN, MarginsPDFHelper.MARGIN_GEN, MarginsPDFHelper.MARGIN_TOP, MarginsPDFHelper.MARGIN_BOT);
try {
PdfReader reader = new PdfReader(pdfByte);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte content = writer.getDirectContent();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
Rectangle pageSize = reader.getPageSizeWithRotation(i);
float scaleX = MarginsPDFHelper.DIM_PAGE.getWidth() / pageSize.getWidth();
float scaleY = MarginsPDFHelper.DIM_PAGE.getHeight() / pageSize.getHeight();
float scale = Math.min(scaleX, scaleY);
content.addTemplate(page, scale, 0, 0, scale, 0, 0);
}
return outputStream.toByteArray();
} catch (Exception e) {
LOGGER.error("Can not scale pdf", e);
} finally {
if (document.isOpen()) {
document.close();
} }
This the result i get after scaling down with itext5
I have two PDF files A and B, I have a requirement where i need to Merge both these PDF files based on a condition.Like,If i find a string like "attach PDF" in my A, i have to merge the B file into A from that particular page in A. For Example,If i spot the word in Page No 3 in my A file I need to merge the B file from Page No:3. I'm using I-Text 5.5.10. Is it possible to achieve this in I-Text or PDFBox. Here is what i have tried as of now.
public static void mergePdf() throws IOException, DocumentException
{
PdfReader reader1 = new PdfReader("C:\\Users\\user1\\Downloads\\generatedSample.pdf");
PdfReader reader2 = new PdfReader("C:\\Users\\user1\\Desktop\\sample1.pdf");
Document document = new Document();
document.addHeader("Header Text", "");
FileOutputStream fos = new FileOutputStream("C:\\Users\\user1\\Downloads\\MergeFile.pdf");
PdfCopy copy = new PdfCopy(document, fos);
document.open();
PdfImportedPage page;
PdfCopy.PageStamp stamp;
Phrase phrase;
BaseFont bf = BaseFont.createFont();
Font font = new Font(bf, 9);
int n = reader1.getNumberOfPages();
for (int i = 1; i <= reader1.getNumberOfPages(); i++)
{
page = copy.getImportedPage(reader1, i);
stamp = copy.createPageStamp(page);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, null, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
for (int i = 1; i <= reader2.getNumberOfPages(); i++)
{
page = copy.getImportedPage(reader2, i);
stamp = copy.createPageStamp(page);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, null, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
document.close();
reader1.close();
reader2.close();
}
Thanks for the solution in advance !!
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.
I have two ByteArrayOutputStreams which contain PDF files.
I used java concatinate operation and it failed.
I want to add the second pdf after the first one.
Is there any Itext functions to merge two Pdfs using streams?
Found it atlast..This one worked for me
Document document = new Document();
//Rectangle pageSize = new Rectangle(792, 612);
Rectangle pageSize = PageSize._11X17;
document.setPageSize(pageSize);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (InputStream in : list) {
PdfReader reader = new PdfReader(in);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
//import the page from source pdf
PdfImportedPage page = writer.getImportedPage(reader, i);
//add the page to the destination pdf
cb.addTemplate(page, 0, 0);
}
}
outputStream.flush();
document.close();
outputStream.close();