I am using iTextSharp to fill in some form fields on a PDF.
PdfReader pdfReader = new PdfReader(templateFile);
//http://stackoverflow.com/questions/17852902/disable-extended-features-with-itextsharp Prevent annoying "extended features disabled" warning in Adobe Reader
pdfReader.RemoveUsageRights();
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(fileName, FileMode.Create), PdfWriter.VERSION_1_7);
pdfStamper.SetFullCompression();
pdfStamper.Writer.CompressionLevel = PdfStream.BEST_COMPRESSION;
AcroFields pdfFormFields = pdfStamper.AcroFields;
// set form pdfFormFields
pdfFormFields.SetField("field1", "value1");
pdfFormFields.SetField("field2", "value2");
pdfFormFields.SetField("field3", "value3");
//etc
pdfStamper.FormFlattening = false;
// close the pdf
pdfStamper.Close();
After filling the PDF fields, I DO NOT flatten the form immediately so manual changes can be made as needed. Once manual changes have been made, I then open the PDF, set maximum compression, flatten the form, save & close the document.
//Move the original file so I can recreate it without editable form fields
string tempFileName = filename + ".temp";
File.Move(filename, tempFileName);
using (PdfReader pdfReader = new PdfReader(tempFileName))
{
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(filename, FileMode.Create), PdfWriter.VERSION_1_7))
{
pdfStamper.SetFullCompression();
pdfStamper.Writer.CompressionLevel = PdfStream.BEST_COMPRESSION;
// flatten the form to remove editting options
pdfStamper.FormFlattening = true;
pdfStamper.Close();
}
pdfReader.Close();
}
//Delete the original temp file
File.Delete(tempFileName);
The first time I run the code directly above to compress and flatten the PDF, the size of each file is slightly decreased, 300KB to 256KB. But, if I run the above code a second time, the file size is greatly reduced, 256KB to 95KB. Subsequent runs do not change the file size any further. My question is, how can I get iTextSharp to output the smallest file size the first time?
EDIT
Removing the compression code from the block that flattens the form results in the same outcome though the final size is slightly larger, 105KB.
The cause of this behavior is simple:
PdfReader, unused objects are immediately dropped. (Not if you work in partial mode, but you don't do that.)PdfStanper, it copies all objects from the PdfReader it stamps and adds some own, not yet written information.Thus,
The small size decrease in the first pass may be due to s few stray unused objects already in the source file or better compression by iTest(Sharp).
The big size decrease in the second pass definitively is due to the dropped form field related objects.
Concerning your question
how can I get iTextSharp to output the smallest file size the first time
You cannot. The stamper in general cannot simply drop the form related objects because they might also be used by different objects. It cannot even check for such usages because other stamper operations executed before might have created new PDF objects which do reference those objects in question, but those newly generated PDF objects have long since been written to output and the stamper cannot access them anymore.
What you can do, though, is to keep the intermediary PDF from appearing on disc by using a MemoryStream as output for pass 1 and input for pass 2.
If you wonder why PdfStamper does not keep those newly created objects in memory to later check for unused objects: iText(Sharp) has been created with server applications and big PDFs in mind; in such a scenario one should write data and free their memory as early as possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With