Merging PDFs with iText 2.1.7 is causing them to shrink - java

I am using iText 2.1.7 to merge some document PDFs into a single PDF. The code below seems to work just fine, however it appears in some instances the rendered PDF is scaled slightly smaller, like at 90% of the PDF if printed directly before processing.
Is there a way to keep the current size?
private void doMerge(List<InputStream> list, OutputStream outputStream) throws DocumentException, IOException {
Document document = new Document();
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();
}

The API was already available with that version. I would even suggest to use PdfSmartCopy instead of PdfCopy (or PdfCopyFields if form fields are inside).
private PdfSmartCopy copier;
public void SomeMainMethod(){
Document finalPdf = new Document();
copier = new PdfSmartCopy(finalPdf, outputstream);
//Start adding pdfs
finalPdf.open();
//add n documents
addDocuments(...);
finalPdf.close();
formCopier.close();
}
public void addDocument(InputStream pdfDocument, int startPage, int endPage){
PdfReader reader= new PdfReader(pdfDocument);
int startPage = 1;
int endPage = reader.getNumberOfPages();
for (int i = startPage; i <= endPage; i++) {
copier.addPage(this.copier.getImportedPage(reader,i));
}
if(copier!=null){
//Important: Free Memory!
copier.flush();
copier.freeReader(reader);
}
if (reader!=null) {
reader.close();
reader=null;
}
pdfDocument.close();
}

Related

Unable to read PDF using itextpdf

I am using itextpdf-5.5.4 jar to merge or add two pdf into one PDF.
I did not get any error or exception while running code but displayed below text in Merged PDF. I did not get below text when i open individual PDF's.
The document you are trying to load requires Adobe Reader 8 or higher.
You may not have the Adobe Reader installed or your viewing
environment may not be properly configured to use Adobe Reader.
For information on how to install Adobe Reader and configure your
viewing environment please see
http://www.adobe.com/go/pdf_forms_configure.
void mergePdfFiles(List<InputStream> inputPdfList, OutputStream outputStream) throws Exception {
// Create document and pdfReader objects.
Document document = new Document();
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
// Create pdf Iterator object using inputPdfList.
Iterator<InputStream> pdfIterator = inputPdfList.iterator();
// Create reader list for the input pdf files.
while (pdfIterator.hasNext()) {
InputStream pdf = pdfIterator.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages = totalPages + pdfReader.getNumberOfPages();
}
// Create writer for the outputStream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
// Open document.
document.open();
// Contain the pdf data.
PdfContentByte pageContentByte = writer.getDirectContent();
PdfImportedPage pdfImportedPage;
int currentPdfReaderPage = 1;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Iterate and process the reader list.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create page and add content.
while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
document.newPage();
pdfImportedPage = writer.getImportedPage(pdfReader, currentPdfReaderPage);
pageContentByte.addTemplate(pdfImportedPage, 0, 0);
currentPdfReaderPage++;
}
currentPdfReaderPage = 1;
}
// Close document and outputStream.
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Pdf files merged successfully.");
}
public static void main(String args[]) {
try {
List<InputStream> inputPdfList = new ArrayList<InputStream>();
inputPdfList.add(new FileInputStream("pdf1.pdf"));
inputPdfList.add(new FileInputStream("pdf2.pdf"));
OutputStream outputStream = new FileOutputStream("Merge-PDF.pdf");
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
mergePdfFiles(inputPdfList, byteStream);
byte[] byteS = byteStream.toByteArray();
outputStream.write(byteS);
} catch (Exception e) {
e.printStackTrace();
}
}
Please help me out on this.

Non removable watermark on PDF file using iText in Java

We have a requirement where we need to add text watermark on magazines which has multiple rich images on each page. I tried com.itextpdf.jar version 5.0.6 to add the watermark but eventually I am able to remove it using Adobe Acrobat Pro.
I tried below option also but that too didn't work.
stamper.setFreeTextFlattening(true);
Is it possible with iText to add a watermark which can not be removed without much effort.
Below is my implementation.
public static void addWaterMark() throws IOException, DocumentException {
PdfReader reader = new PdfReader("C:/Trade-catalog/Catalog2017.pdf");
ByteArrayOutputStream outputPdf = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, outputPdf);
String bodyWatermarkText = "12345 - John Smith";
String bodyWatermarkRotation = "35";
String footerWatermarkText = "Richard Parker";
BaseFont font = BaseFont.createFont("/fonts/micross.ttf", "Cp1250", BaseFont.EMBEDDED);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
Rectangle thisPageSize = reader.getPageSize(i);
PdfPatternPainter bodyPainter = stamper.getOverContent(i).createPattern(thisPageSize.getWidth(),
thisPageSize.getHeight());
bodyPainter.setColorFill(new BaseColor(0, 0, 0));
bodyPainter.beginText();
bodyPainter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_FILL);
bodyPainter.setFontAndSize(font, 60);
bodyPainter.showTextAlignedKerned(Element.ALIGN_CENTER, bodyWatermarkText, thisPageSize.getWidth() / 2,
thisPageSize.getHeight() / 2, Integer.valueOf(bodyWatermarkRotation));
bodyPainter.showTextAlignedKerned(Element.ALIGN_RIGHT, footerWatermarkText, thisPageSize.getWidth() * 0.97f,
thisPageSize.getHeight() * 0.015f, 0);
bodyPainter.endText();
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setGState(state);
overContent.setColorFill(new PatternColor(bodyPainter));
overContent.rectangle(thisPageSize.getLeft(), thisPageSize.getBottom(), thisPageSize.getWidth(),
thisPageSize.getHeight());
overContent.fill();
overContent.setFlatness(100);
}
stamper.close();
FileOutputStream outputStream = new FileOutputStream(
"C:/Trade-catalog/output/TradeCatalog2017Watermarked_bodyPainter.pdf");
outputPdf.writeTo(outputStream);
outputPdf.close();
reader.close();
}

How can I merge the documents consisting PDFs as well as images?

In my current code I am merging the documents consisting PDF files.
public static void appApplicantDownload(File file) {
Connection con = getConnection();
Scanner sc = new Scanner(System.in);
List < InputStream > list = new ArrayList < InputStream > ();
try {
OutputStream fOriginal = new FileOutputStream(file, true); // original
list.add(new FileInputStream(file1));
list.add(new FileInputStream(file2));
list.add(new FileInputStream(file3));
doMerge(list, fOriginal);
} catch (Exception e) {
}
}
public static void doMerge(List < InputStream > list, OutputStream outputStream) throws DocumentException, IOException {
try {
System.out.println("Merging...");
Document document = new Document();
PdfCopy copy = new PdfCopy(document, outputStream);
document.open();
for (InputStream in : list) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
IOUtils.copy( in , b);
PdfReader reader = new PdfReader(b.toByteArray());
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
copy.addPage(copy.getImportedPage(reader, i));
}
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
But now I want to change the code such that it should allow Image as well as PDFs to be merged. Above code is giving me the error that No PDF Signature found
First, you have to know somehow if the file is a PDF or an image. The easiest way would be to use the extension of the file. So you would have get extension of the file and then pass this information to your doMerge method. Do achieve that, I would change your current method
public static void doMerge(List<InputStream> list, OutputStream outputStream)
For something like
public static void doMerge(Map<InputStream, String> files, OutputStream outputStream)
So each InputStream is associated with a extension.
Second, you have to load images and pdf seperately. So your loop should look like
for (InputStream in : files.keySet()) {
String ext = files.get(in);
if(ext.equalsIgnoreCase("pdf"))
{
//load pdf here
}
else if(ext.equalsIgnoreCase("png") || ext.equalsIgnoreCase("jpg"))
{
//load image here
}
}
In java, you can easily load an Image using ImageIO. Look at this question for more details on this topic: Load image from a filepath via BufferedImage
Then to add your image into the PDF, use the PdfWriter
PdfWriter pw = PdfWriter.GetInstance(doc, outputStream);
Image img = Image.GetInstance(inputStream);
doc.Add(img);
doc.NewPage();
If you want to convert your image into PDF before and merge after you also can do that but you just have to use the PdfWriter to write them all first.
Create a new page in the opened PDF document and use the function for inserting images to place the image on that page.

Merge pdf documents of different width using iText

I am having problem while merging documents of different width using iText.
Below is the code I'm using to merge.
public static void doMerge(List<InputStream> list, OutputStream outputStream) throws Exception {
Rectangle pagesize = new Rectangle(1700f, 20f);
com.itextpdf.text.Document document = new com.itextpdf.text.Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
document.setPageSize(pagesize);
com.itextpdf.text.pdf.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
com.itextpdf.text.pdf.PdfImportedPage page = writer.getImportedPage(reader, i);
//calculate the y for merging it from top
float y = document.getPageSize().getHeight() - page.getHeight();
//add the page to the destination pdf
cb.addTemplate(page, 0, y);
}
reader.close();
in.close();
}
outputStream.flush();
document.close();
outputStream.close();
}
First page of pdf will be of 14 inch of width and 13 inch of height. All the other pages on document will be always smaller than it.
I want to merge all the documents altogether in a single document.
I don't know how to set a width and height of a single merged document.
I think Rectangle pagesize = new Rectangle(1700f, 20f); should do it but it's not working means if change it to Rectangle pagesize = new Rectangle(1700f, 200f);, document has no effect.
Please guide me further.
Using the PdfWriter class to merge documents goes against all the recommendations given in the official documentation, though there are unofficial examples that may have lured you into writing bad code. I hope that you understand that I find these bad examples even more annoying than you do.
Please take a look at Table 6.1 in chapter 6 of my book. It gives you an overview showing when to use which class. In this case, you should use PdfCopy:
String[] files = { MovieLinks1.RESULT, MovieHistory.RESULT };
// step 1
Document document = new Document();
// step 2
PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT));
// step 3
document.open();
// step 4
PdfReader reader;
int n;
// loop over the documents you want to concatenate
for (int i = 0; i < files.length; i++) {
reader = new PdfReader(files[i]);
// loop over the pages in that document
n = reader.getNumberOfPages();
for (int page = 0; page < n; ) {
copy.addPage(copy.getImportedPage(reader, ++page));
}
copy.freeReader(reader);
reader.close();
}
// step 5
document.close();
If you are using a recent version of iText, you can even use the addDocument() method in which case you don't need to loop over all the pages. You also need to take special care if forms are involved. There are several examples demonstrating the new functionality (dating from after the book was written) in the Sandbox.
with the itext version 5.5 we can merge pdf more easly using the method PdfCopy.addDocument :
package tn.com.sf.za.rd.controller;
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
public class ReportMerging {
public static void main(String[] args) throws DocumentException, IOException {
String DOC_ONE_PATH = "D:/s.zaghdoudi/tmp/one.pdf";
String DOC_TWO_PATH = "D:/s.zaghdoudi/tmp/two.pdf";
String DOC_THREE_PATH = "D:/s.zaghdoudi/tmp/three.pdf";
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(DOC_THREE_PATH));
document.open();
PdfReader readerOne = new PdfReader(DOC_ONE_PATH);
PdfReader readerTwo = new PdfReader(DOC_TWO_PATH);
copy.addDocument(readerOne);
copy.addDocument(readerTwo);
document.close();
}
}

How can I remove the first page of a PDF file with Java?

I was thinking about using a library such as PDFBox but I would like your input.
I can recommend iText, it works pretty well for manipulating PDFs or even constructing them from scratch.
There is also a tutorial on how to manipulate PDFs. I didn't see a way to delete pages, but the tool supports creating a new PDF by copying content from another one. So you could just copy all the pages but the first.
With IText
public void removeFirstPage(String input_filename, String output_filename) throws DocumentException, IOException {
File outFile = new File(output_filename);
PdfReader reader = new PdfReader(input_filename);
int pages_number = reader.getNumberOfPages();
if(pages_number > 0) {
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy copy = new PdfCopy(document, new FileOutputStream(outFile));
document.open();
for(int i=2; i <= pages_number;i++) {
PdfImportedPage page = copy.getImportedPage(reader, i);
copy.addPage(page);
}
document.close();
}
}

Categories