Hi Fabrizio,
Thank you for your checker code. Here is a line or two I added to see the
messages:
for (int i = 0; i < chk.Messages.Length; i++)
Console.WriteLine(chk.Messages[i]);
It shows the generated PDF having 2 levels and the one from CutePDF with 1
level. But the telling story is the messages show the generated PDF has 1 or 2
'CurrentLevel's for each page and 1 or more objects with page 2 having about 25
objects. There are 12 pages in all. The equivalent CutePDF output PDF shows
only 1 'CurrentLevel' on each page and no objects at all.
You are correct in your understanding of how I build/concatenate the PDFs to
create one final PDF.
What follows is code that I wrote for this process. The first method is
WriteDocument that fills in the forms data fields. The next code snippet is an
example of the higher level code that takes the two memory streams and merges
them by a call to MergePDFFileStreams. The MergePDFFileStreams method calls a
PdfConcat method which I have three of...these are the ones that all work but
didn't solve my problem.
Note that this code may not be optimized for the number of MemoryStreams that
are created and destroyed and some of that may be unnecessary. But at the time
of creation of this code I wanted to elliminate all possibilities of having
memory problems while debugging the merge mechanism. So I may actually end up
not doing so much of that which is found in the MergePDFFileStreams and
PdfConcat methods..
/// <summary>
/// This method writes data into a PDF file's fields. Each field in the
PDF file must be a
/// different name and the corresponding data must match the name that
is installed in the
/// hash table used for the fields.
/// </summary>
/// <param name="stream"></param>
/// <param name="suffix"></param>
/// <returns></returns>
public bool WriteDocument(Stream stream, String suffix)
{
String filePath = GetFormFile(suffix);
if (!File.Exists(filePath))
return false;
PdfReader pdfReader = new PdfReader(filePath);
MemoryStream memStream = new MemoryStream();
PdfStamper stamp = new PdfStamper(pdfReader, memStream);
stamp.Writer.CloseStream = false;
AcroFields form = stamp.AcroFields;
Object objValue;
String fieldName = "";
String fieldValue = "";
Hashtable formFields = form.Fields;
foreach (DictionaryEntry de in formFields)
{
fieldName = (String)de.Key;
objValue = this.data[fieldName];
if (objValue != null)
{
fieldValue = (String)objValue;
form.SetField(fieldName, fieldValue);
}
}
stamp.FormFlattening = true; // remove editable fields thereby
making them part of the document.
stamp.Close();
memStream.WriteTo(stream);
memStream.Close();
return true;
}
======= CODE SNIPPET =====
MemoryStream baseStream;
MemoryStream tmpStream;
// For the first PDF just instantiate baseStream directly to get started.
// ...
// For follow on merging of two streams use something like the following. Note
// the LoadCareerObjectivesReferencesData is where the WriteDocument is called.
tmpStream = new MemoryStream();
if (!LoadCareerObjectivesReferencesData(ref tmpStream))
{
baseStream.Close();
tmpStream.Close();
return false;
}
baseStream = MergePDFFileStreams(baseStream, tmpStream);
=========================
/// <summary>
/// Merges two memory streams and returns a resulting memory stream.
This method closes and
/// disposes of the two input streams before returning.
/// </summary>
/// <param name="baseStream"></param>
/// <param name="concatStream"></param>
/// <returns>resulting memory stream</returns>
private MemoryStream MergePDFFileStreams(Stream baseStream, Stream
concatStream)
{
// Reset pointers to the beginning of the memory stream since the
expected streams
// were just built and probably have their pointers set to the end
of the stream.
baseStream.Seek(0, SeekOrigin.Begin);
concatStream.Seek(0, SeekOrigin.Begin);
MemoryStream resultStream = PdfConcat3(baseStream, concatStream);
// Not sure if the PdfConcat resets the pointer back to the
beginning of the stream
// so we do it here for insurance.
resultStream.Seek(0, SeekOrigin.Begin);
baseStream.Close();
baseStream.Dispose();
concatStream.Close();
concatStream.Dispose();
return resultStream;
}
// Here are the 3 PdfConcat methods. Currently I am using PdfConcat3. They all
work.
protected MemoryStream PdfConcat(Stream readerBase, Stream readerConcat)
{
// creation of the resulting memory stream to be returned
MemoryStream outputStream = new MemoryStream();
PdfReader reader = new PdfReader(readerBase);
int n = reader.NumberOfPages;
Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfWriter writer = PdfWriter.GetInstance(document, outputStream);
writer.CloseStream = false;
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
for (int j = 0; j < 2; j++)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
if (j == 0)
{
reader = new PdfReader(readerConcat);
n = reader.NumberOfPages;
}
}
document.Close();
return outputStream;
}
protected MemoryStream PdfConcat2(Stream readerBase, Stream
readerConcat)
{
// creation of the resulting memory stream to be returned
MemoryStream outputStream = new MemoryStream();
PdfReader reader = new PdfReader(readerBase);
int n = reader.NumberOfPages;
Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, outputStream);
writer.CloseStream = false;
document.Open();
PRAcroForm form;
PdfImportedPage page;
for (int j = 0; j < 2; j++)
{
int i = 0;
while (i < n)
{
i++;
page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
form = reader.AcroForm;
if (form != null)
writer.CopyAcroForm(reader);
// setup to do the form to be concatenated
if (j == 0)
{
reader = new PdfReader(readerConcat);
reader.ConsolidateNamedDestinations();
n = reader.NumberOfPages;
}
}
document.Close();
return outputStream;
}
protected MemoryStream PdfConcat3(Stream readerBase, Stream
readerConcat)
{
// creation of the resulting memory stream to be returned
MemoryStream outputStream = new MemoryStream();
PdfReader reader1 = new PdfReader(readerBase);
PdfReader reader2 = new PdfReader(readerConcat);
PdfCopyFields copy = new PdfCopyFields(outputStream);
copy.Writer.CloseStream = false;
copy.AddDocument(reader1);
copy.AddDocument(reader2);
copy.Close();
return outputStream;
}
=================================
I used some shareware called PDF-Analyzer 3.0 to look at both these PDFs and
saw that CutePDF uses Ghostscript. I then went looking at Ghostscript and saw
that there is a pdfopt (PDF Optimizer) feature which is probably what I need as
a truely final step in this process. However, I can not yet find that pdfopt
feature so I am downloading the source...I am hoping it is available in the
public GPL release. I was actually hoping that iText had some optimizer code or
that there might be some optimization code samples somewhere but I haven't
found any at least not net.
I can supply you with the two PDF files, the one I generate and the one that
CutePDF outputs so you can see the comparison for yourself if you like.
Thanks,
Gery
Gery D. Dorazio
Development Engineer
EnQue Corp.
phone: 704.377.3327
email : [EMAIL PROTECTED]
web : www.EnQue.net
----- Original Message -----
From: Fabrizio Accatino
To: Post all your questions about iText here
Sent: Thursday, December 06, 2007 3:11 AM
Subject: Re: [iText-questions] limitcheck gsave error
Post source code. I think it was usefull to understand how you build
your pdf (I haven't undestood).
AFAIK, CutePdf is based on Ghostscript, and AFAIK Ghostscript try to
reduce the level of nested xobject in pdf files. This explains why pdf
printed on CutePdf and then printed on a PS printer does not hang.
I haven't understood how you build your pdf. It seems that I merge 2
pdf (A+B) and get the result (file T1). Then you add C to T1 and get
T2, then add D to T2 and get T3 and so on. Am I right? If it is so,
you create a very deep list of nested xobject in the pdf.
I have wrote a small piece of code to count the level of nested
xobject. Try to use it to check your pdf files during your process.
http://fhtino.blogspot.com/2007/10/level-of-nested-xobject-in-pdf-file.html
Fabrizio
On Dec 5, 2007 10:39 PM, Gery D. Dorazio <[EMAIL PROTECTED]> wrote:
>
>
>
> I have several PDF files with fields that get populated with data.
> These forms get combined to form a single PDF which is then
> sent to a users browser.
>
> .............................
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions
Buy the iText book: http://itext.ugent.be/itext-in-action/
__________ NOD32 2705 (20071205) Information __________
This message was checked by NOD32 antivirus system.
http://www.eset.com
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions
Buy the iText book: http://itext.ugent.be/itext-in-action/