I had a fillable PDF document (2 pages in total) consisting of different sizes of page; the first page is 8.5 * 11 inches (612 * 792), containing fillable fields; the second page is 9.5 * 12 inches (684 * 864), containing No fillable fields. Even though the second page is larger, the margin of it can be ignored. In other word, if get the second page printed as A4, no content would be cut.
However, when I am doing the document concatenation(using 612 *792), all second pages will be lined up at the left bottom corner of the page, making partial contents lost on top and right margin of the page. Even though full content can be fit in when (684 *864) is applied, all first pages are lined up at the left bottom corner of the page as well, making it a wide blank margins on top and right of page.
Is there anyway that I can get pages be written in center of page all the times so that I can use size of 612* 792 without losing contents in second pages?
Below is the concatenation method:
private static byte[] ConcatContents(List<byte[]> pdf)
{
byte[] all;
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document(new Rectangle(612, 792));
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
doc.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
PdfReader reader;
foreach (byte[] p in pdf)
{
reader = new PdfReader(p);
int pages = reader.NumberOfPages;
// loop over document pages
for (int i = 1; i <= pages; i++)
{
doc.NewPage();
page = writer.GetImportedPage(reader, i);
cb.AddTemplate(page, 0, 0);
}
}
doc.Close();
all = ms.ToArray();
ms.Flush();
ms.Dispose();
}
return all;
}
[UPDATE]
Original Page Size difference in PDF
After Page concatenation, some of the content lost because it seems like PDF was generated from left bottom corner up. The page size difference causes the lost of page content. As you can see in the picture below, the first line of second page content
"BECUASE THIS FORM IS USED BY VARIOUS GOVERNMENT..."
was cut off, as well as some content in the right.
Well, Thanks to plinth's suggestions, I found out that the below code work perfectly to adjust all the second pages to center of the page. Although it doesn't look like a good practice, it works eventually.
// loop over document pages
for (int i = 1; i <= pages; i++)
{
doc.NewPage();
page = writer.GetImportedPage(reader, i);
if (i == 1)
{
cb.AddTemplate(page, 0, 0);
}
else
{
float page1Height, page1Width, page2Height, page2Width;
page1Height = reader.GetPageSizeWithRotation(i - 1).Height;
page1Width = reader.GetPageSizeWithRotation(i - 1).Width;
page2Height = reader.GetPageSizeWithRotation(i).Height;
page2Width = reader.GetPageSizeWithRotation(i).Width;
cb.AddTemplate(page, (page1Width - page2Width) / 2, (page1Height - page2Height) / 2);
}
}
Here is the displayed result
Related
I have some code used to watermark PDFs using iTextSharp. The code works fine for most PDFs, but there has been one test case where the watermark is not visible on a PDF of a scanned document. (I have other scanned documents where it does appear though).
I am using the GetOverContent() method.
This is my code for adding the watermark;
using (PdfReader reader = new PdfReader(this.inputFilename))
{
// Set transparent - 1
PdfGState gstate = new PdfGState();
gstate.FillOpacity = 0.4f;
gstate.StrokeOpacity = 0.5f;
// 2
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
using (var stream = new MemoryStream())
{
var pdfStamper = new PdfStamper(reader, stream);
// Must start at 1 because 0 is not an actual page.
for (int i = 1; i <= reader.NumberOfPages; i++)
{
Rectangle pageSize = reader.GetPageSizeWithRotation(i);
// Gets the content ABOVE the PDF, Another option is GetUnderContent(...)
// which will place the text below the PDF content.
PdfContentByte pdfPageContents = pdfStamper.GetOverContent(i);
pdfPageContents.BeginText(); // Start working with text.
// 1
pdfPageContents.SaveState();
pdfPageContents.SetGState(gstate);
float hypotenuse = (float)Math.Sqrt(Math.Pow(pageSize.Width, 2) + Math.Pow(pageSize.Height, 2));
float glyphWidth = baseFont.GetWidth("My watermark text");
float fontSize = 1000 * (hypotenuse * 0.8f) / glyphWidth;
float angle = (float)(Math.Atan(pageSize.Height / pageSize.Width) * (180 / Math.PI));
// Create a font to work with
pdfPageContents.SetFontAndSize(baseFont, fontSize);
pdfPageContents.SetRGBColorFill(128, 128, 128); // Sets the color of the font, GRAY in this instance
// Note: The x,y of the Pdf Matrix is from bottom left corner.
// This command tells iTextSharp to write the text at a certain location with a certain angle.
// Again, this will angle the text from bottom left corner to top right corner and it will
// place the text in the middle of the page.
pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "My watermark text", pageSize.Width / 2, pageSize.Height / 2, angle);
pdfPageContents.EndText(); // Done working with text
pdfPageContents.RestoreState();
}
pdfStamper.FormFlattening = true; // enable this if you want the PDF flattened.
pdfStamper.FreeTextFlattening = true; // enable this if you want the PDF flattened.
pdfStamper.Close(); // Always close the stamper or you'll have a 0 byte stream.
return stream.ToArray();
}
}
Does anyone have any ideas as to why the watermark may not be appearing and what I can try to fix it?
Kind regards.
The code is based on an assumption it even documents as a fact:
// Note: The x,y of the Pdf Matrix is from bottom left corner.
// This command tells iTextSharp to write the text at a certain location with a certain angle.
// Again, this will angle the text from bottom left corner to top right corner and it will
// place the text in the middle of the page.
pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "My watermark text", pageSize.Width / 2, pageSize.Height / 2, angle);
The assumption that the x,y of the Pdf Matrix is from bottom left corner unfortunately is wrong: While it indeed is very often the case that the origin of the PDF coordinate system (the default user space coordinate system, to be more precise) is in the lower left corner of the page, this is not required, the origin actually can be literally anywhere (within reasonable limits).
Thus, one has to take the lower left coordinates of the Rectangle pageSize into consideration, too.
The OP meanwhile has confirmed:
I had assumed that the bottom left of the page would have co-ordinates of (0,0) but for this document the co-ordinates were (0, 7022).
I want to create a pdf file using itext that has unequal page sizes.
I have these two rectangles:
Rectangle one=new Rectangle(70,140);
Rectangle two=new Rectangle(700,400);
and i am writing to the pdf like this :
Document document = new Document();
PdfWriter writer= PdfWriter.getInstance(document, new FileOutputStream(("MYpdf.pdf")));
when I create the document, I have the option to specify the page size , but I want different page sizes for different pages in my pdf.
Is it possible to do that ?
Eg. The first page will have rectangle one as the page size, and the second page will have rectangle two as the page size.
I've created an UnequalPages example for you that shows how it works:
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(dest));
Rectangle one = new Rectangle(70,140);
Rectangle two = new Rectangle(700,400);
document.setPageSize(one);
document.setMargins(2, 2, 2, 2);
document.open();
Paragraph p = new Paragraph("Hi");
document.add(p);
document.setPageSize(two);
document.setMargins(20, 20, 20, 20);
document.newPage();
document.add(p);
document.close();
It is important to change the page size (and margins) before the page is initialized. The first page is initialized when you open() the document, all following pages are initialized when a newPage() occurs. A new page can be triggered explicitly (using the newPage() method in your code) or implicitly (by iText, when a page was full and a new page is needed).
I want to build a container around an existing PDF page, so actually enlarge that document and put it in the middle so that I can write more things into.
What I tried so far :
// Open the file
PdfDocument inputDocument = PdfReader.Open(filename, PdfDocumentOpenMode.Import);// PdfReader.Open(filename, PdfDocumentOpenMode.Modify);
PdfDocument newContainerDocument = new PdfDocument();
// Create an empty page or load existing
for (int idx = 0; idx < inputDocument.PageCount; idx++)
{
PdfPage page = new PdfPage(); //this should be the actual container
page.Width = tempWidth;
page.Height = tempHeight;
//gfx.DrawImage(image, (page.Width / 2) - (width / 2), (page.Height / 2) - (height / 2), width, height); //put it in the middle of the container, this would only work with IMAGES ... using "XGraphics"
// Add the page and save it
newContainerDocument.AddPage(inputDocument.Pages[idx]);
}
newContainerDocument.Save(String.Format("{0} - Page {1}_expandedFile.pdf", insertName,DateTime.Now.Ticks.ToString()));
inputDocument.Close();
newContainerDocument.Close();
But I get:
The document cannot be modified
What is wrong here ?
Thank you
PdfDocumentOpenMode.Import is for import, allowing you to copy pages to a new file.
PdfDocumentOpenMode.Modify is for modifications.
I think the problem is that you do not copy pages, you add existing pages to a new document.
Your code might work with Clone():
newContainerDocument.AddPage((PdfPage)inputDocument.Pages[idx].Clone());
I would create a new page and draw the existing page onto that page, as this sample does:
http://pdfsharp.net/wiki/TwoPagesOnOne-sample.ashx
I have a problem with regards on the page orientation of the paper size.
I have a pdf file which contains portrait and landscape page.
this code works perfectly.
string FileLocation = "c:\\Temp\\SomeFile.pdf";
string WatermarkLocation = "c:\\Temp\\watermark.gif";
Document document = new Document();
PdfReader pdfReader = new PdfReader(FileLocation);
PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(FileLocation.Replace(".pdf","[temp][file].pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(WatermarkLocation);
img.SetAbsolutePosition(250,300); // set the position in the document where you want the watermark to appear (0,0 = bottom left corner of the page)
PdfContentByte waterMark;
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
waterMark = stamp.GetUnderContent(page);
waterMark.AddImage(img);
}
stamp.FormFlattening = true;
stamp.Close();
// now delete the original file and rename the temp file to the original file
File.Delete(FileLocation);
File.Move(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileLocation);
since I'm using absolute value to set the image position.
img.SetAbsolutePosition(250,300);
How can T set the image position if the page is landscape or portrait?
note: One pdf with landscape and portrait page orientation.
Is there by chance that I can use if statement?
if (//paper is landscape)
{
//code here
}
else
{
//code here
}
What do you want to achieve?
Normally, iText takes into account the value of the page rotation. This means that when a page is rotated, the coordinates will be rotated too.
If you want to overrule this, you can add this line:
stamper.RotateContents = false;
This is explained in Chapter 6 of my book. You can try this example to see the difference:
No rotation, text added normally: hello1.pdf
Rotation, text added normally ( = rotated): hello2.pdf
Rotation, text added with rotation ignored: hello3.pdf
Of course, this assumes that a rotation was defined for the pages. Sometimes, landscape is mimicked by defining a different page size instead of defining a rotation.
In that case, you should also read Chapter 6 because it explains how to get the MediaBox of a document. see the example PageInformation that introduces methods such as GetPageSize(), GetRotation() and GetPageSizeWithRotation().
This is all documented, but if it doesn't answer your question, please clarify. As demonstrated in the example, the rotation is taken into account by default when adding new content, so maybe I misunderstood the question.
I have a table and a chart to be added to a PDF Document. I have used the iTextSharpLibrary to add the contents to the PDF file.
Actually the problem is that the chart has a width of 1500px and the table fits in comfortably in an A4 page size.
Actually the chart image that I get must not be scaled to fit in the page as it reduces the viewability. Hence, I need to add a new page that has a wider width than the other ones or at least change the page orientation to landscape and then add the image. How do I do this?
This is the code that I used to add a new page and then resize the page and then add the image. This is not working. Any fixes?
var imageBytes = ImageGenerator.GetimageBytes(ImageSourceId);
var myImage = iTextSharp.text.Image.GetInstance(imageBytes);
document.NewPage();
document.SetPageSize(new Rectangle(myImage.Width, myImage.Height));
myImage.ScaleToFit(document.PageSize.Width, document.PageSize.Height);
document.Add(myImage);
I fixed the Issue. I have to set the page size before calling the GetInstance of the Pdfdocument. Then, i can give different pagesizes for each page
I'm not sure what you mean by before calling the GetInstance of the Pdfdocument, but setting the pageSize right before calling newPage works.
Here follows the c# code to create a new pdf that's made of two pictures, no matter how wild their sizes difference is. The important lines here are the new Document and SetPageSize ones.
static public void MakePdfFrom2Pictures (String pic1InPath, String pic2InPath, String pdfOutPath)
{
using (FileStream pic1In = new FileStream (pic1InPath, FileMode.Open))
using (FileStream pic2In = new FileStream (pic2InPath, FileMode.Open))
using (FileStream pdfOut = new FileStream (pdfOutPath, FileMode.Create))
{
//Load first picture
Image image1 = Image.GetInstance (pic1In);
//I set the position in the image, not during the AddImage call
image1.SetAbsolutePosition (0, 0);
//Load second picture
Image image2 = Image.GetInstance (pic2In);
// ...
image2.SetAbsolutePosition (0, 0);
//Create a document whose first page has image1's size.
//Image IS a Rectangle, no need for new Rectangle (Image.Width, Image.Height).
Document document = new Document (image1);
//Assign writer
PdfWriter writer = PdfWriter.GetInstance (document, pdfOut);
//Allow writing
document.Open ();
//Get writing head
PdfContentByte pdfcb = writer.DirectContent;
//Put the first image on the first page
pdfcb.AddImage (image1);
//The new page will have image2's size
document.SetPageSize (image2);
//Add the new second page, and start writing in it
document.NewPage ();
//Put the second image on the second page
pdfcb.AddImage (image2);
//Finish the writing
document.Close ();
}
}