I have researched this and tried to rotate a single page PDF's contents. I am able to rotate the page 90, 180 or 270 degrees. I don't want to rotate the page but rather the contents.
Here's the method I have adapted so far:
public static byte[] RotatePdf(byte[] fileBytes, int degreesClockwise)
{
if (degreesClockwise % 90 != 0)
throw new ApplicationException(string.Format("degreesClockwise must be 0, 90, 180, 360: {0}", degreesClockwise));
PdfReader reader = new PdfReader(fileBytes);
using (var fs = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(reader, fs);
PdfDictionary pageDict = reader.GetPageN(1);
int desiredRotation = degreesClockwise; // x degrees clockwise from what it is now
PdfNumber rotation = pageDict.GetAsNumber(PdfName.ROTATE);
if (rotation != null)
{
desiredRotation += rotation.IntValue;
desiredRotation %= 360; // must be 0, 90, 180, or 270
}
pageDict.Put(PdfName.ROTATE, new PdfNumber(desiredRotation));
stamper.Close();
return fs.ToArray();
}
}
Any suggestions would be greatly appreciated.
I accomplished the code using the PdfSharp library as I could not find any examples or answers for iTextSharp unfortunately.
Here is the code I used to accomplish what I wanted:
// Create the output document
PdfDocument outputDocument = new PdfDocument();
// Show single pages
// (Note: one page contains two pages from the source document)
outputDocument.PageLayout = PdfPageLayout.SinglePage;
// Open the external document as XPdfForm object
XPdfForm form = XPdfForm.FromFile(filename);
for (int i = 0; i < form.PageCount; i++)
{
// Add a new page to the output document
PdfPage page = outputDocument.AddPage();
page.Orientation = PageOrientation.Landscape;
double width = page.Width;
double height = page.Height;
int rotate = page.Elements.GetInteger("/Rotate");
XGraphics gfx = XGraphics.FromPdfPage(page);
XRect box = new XRect(0, 0, width, height * 2);
// Draw the page identified by the page number like an image
gfx.DrawImage(form, box);
}
// Save the document...
filename = "RotatedAndStretched_tempfile.pdf";
outputDocument.Save(filename);
Related
Im working on a project where i have to resize a pdf file as input ( from A3 to A4 ), respecting the right rotation of the original document and at end add Margins all around the content.
Im using actually iTextSharp to do this, but my problem that i manage to do the resize and rotation part, but NO OK for the margins (code bellow). The SetMargins() don't change any marging !
Please anyone ca me solve this problem ?
Thanks in advance
/// Start resizing
/// using iTextsharp lib
/// Read the input file
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(filePath);
/// GĂ©nerate the new file
Document doc = new Document() ;
/// Check input PDF rotation
iTextSharp.text.Rectangle rectangle = reader.GetPageSizeWithRotation(1);
if (rectangle.Height < rectangle.Width)
{
label7.Text = "Paysage";
rotation = 90;
}
else
{
label7.Text = "Portrait";
rotation = 0;
}
/// Create new A4 pdf with the correct rotation
if (rotation == 0)
{
doc = new Document(PageSize.A4);
doc.SetMargins(50, 50, 50, 50);
float marg = doc.BottomMargin;
}
else if (rotation == 90)
{
doc = new Document(PageSize.A4.Rotate());
doc.SetMargins(50, 50, 50, 50);
float marg = doc.BottomMargin;
}
/// Start generating the new PDF
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc,new FileStream("Testing folder/" + fileNameWithoutExtention+"_mod.PDF",FileMode.Create));
/// Open the new PDF and manage content
doc.Open();
for (int i = 1; i <= pagesNbr; i++)
{
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page = writer.GetImportedPage(reader, i);
float Scale = 0.67f;
doc.NewPage();
cb.AddTemplate(page, Scale, 0, 0, Scale, 0, 0);
}
this code generate a new PDF with the right size A4, right orientation, but the content is on the left-bottom side of the page ! i need it to be in the center of the page and i can manage the margins !
I am using the below code to add watermark to my pdf.
private void Merge(List<string> src, string dest)
{
iTextKernel.PdfWriter writer = new iTextKernel.PdfWriter(dest);
iTextKernel.PdfDocument pdfDocument1 = new iTextKernel.PdfDocument(new iTextKernel.PdfReader(src[0]), writer);
pdfDocument1.AddEventHandler(PdfDocumentEvent.END_PAGE, new WatermarkingEventHandler());
for (int i = 1, max = src.Count; i < max; i++)
{
iTextKernel.PdfDocument pdfDocument2 = new iTextKernel.PdfDocument(new iTextKernel.PdfReader(src[i]));
var pagesCount = pdfDocument2.GetNumberOfPages();
pdfDocument2.CopyPagesTo(1, pagesCount, pdfDocument1);
pdfDocument2.Close();
}
pdfDocument1.Close();
protected class WatermarkingEventHandler : IEventHandler {
public void HandleEvent(Event e) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) e;
iTextKernel.PdfDocument pdfDoc = docEvent.GetDocument();
iTextKernel.PdfPage page = docEvent.GetPage();
iText.Kernel.Font.PdfFont font = null;
try {
font = PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD);
} catch (IOException ex) {
//_log.Error(ex);
}
PdfCanvas canvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
new Canvas(canvas, pdfDoc, page.GetPageSize())
.SetFontColor(iText.Kernel.Colors.DeviceGray.LIGHT_GRAY)
.SetFontSize(60)
.SetFont(font)
.ShowTextAligned(new Paragraph("FOR YOUR RECORDS ONLY: DO NOT SUBMIT"), 298, 421, pdfDoc.GetPageNumber(page),
TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
}
But am getting the watermark only in the last page that too hidden under the contents. Could you please modify this code so that i could get the watermark on all the pages and shown over the contents.
Please take a look at the iText 7 for C# jump-start tutorial, more specifically Chapter 5: Manipulating an existing PDF document. Scroll to the part where it says: "Adding a header, footer, and watermark" and look at the example:
PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
Document document = new Document(pdfDoc);
Rectangle pageSize;
PdfCanvas canvas;
int n = pdfDoc.GetNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = pdfDoc.GetPage(i);
pageSize = page.GetPageSize();
canvas = new PdfCanvas(page);
//Draw header text
}
pdfDoc.close();
As you can see, we only need one PdfDocument instance, but instead of passing only a PdfWriter, we also pass a PdfReader instance. We will read the file with path src and we will write to a file with path dest.
You want to add content to each page. This means that you have to loop over each page (from 1 to n). Get the PdfPage object for each page i and replace the line //Draw header text with whatever it is you want to do.
In your case, you add an image underneath the existing content. That is the normal thing to do, but you say that the watermark is covered by the existing content. That happens for instance when the actual content consists of images (e.g. scanned pages). If you add a watermark under the pages of a PDF that consists of scanned pages, you will never see the watermark.
In that case, you have to add the content on top of the existing content, but it is best to make the watermark transparent:
Paragraph p = new Paragraph("FOR YOUR RECORDS ONLY: DO NOT SUBMIT").SetFontSize(60);
canvas.SaveState();
PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.2f);
canvas.SetExtGState(gs1);
document.ShowTextAligned(p, pageSize.GetWidth() / 2, pageSize.GetHeight() / 2, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
canvas.RestoreState();
Note that in the tutorial, we are using pageSize.GetWidth() / 2 and pageSize.GetHeight() / 2 as coordinates, which means that we assume that the lower-left corner of the page has the coordinate (0, 0). That may not be the case. You may have to add the x-offset and the y-offset to that value.
This question already has an answer here:
Tile PDF pages vertically with iTextSharp
(1 answer)
Closed 8 years ago.
I am trying to divide a PDF into exactly 2 equal halves, saving them as "LeftPDF.pdf" and "RightPDF.pdf".
I tried the code below but it doesn't work:
PdfReader reader = new PdfReader(filepath);
int n = reader.NumberOfPages;
iTextSharp.text.Rectangle psize = reader.GetPageSize(1);
float width = psize.Width/2;
float height = psize.Height;
Document document = new Document(psize);
// target.pdf is A5 Portrait format
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(splitpath, FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
document.NewPage();
PdfImportedPage page1 =writer.GetImportedPage(reader, 1);
cb.AddTemplate(page1, 1, 0, 0, 1, 0, 0);
document.Close();
How can I do this?
As I indicated in my comment, your question has been posted and answered before. This is yet another duplicate of your question: Divide one page PDF file in two pages PDF file
Take a closer look at the TileInTwo example:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
// step 1
Rectangle mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(1)));
Document document = new Document(mediabox);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte content = writer.getDirectContent();
PdfImportedPage page;
int i = 1;
while (true) {
page = writer.getImportedPage(reader, i);
content.addTemplate(page, 0, -mediabox.getHeight());
document.newPage();
content.addTemplate(page, 0, 0);
if (++i > n)
break;
mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(i)));
document.setPageSize(mediabox);
document.newPage();
}
// step 5
document.close();
reader.close();
}
public Rectangle getHalfPageSize(Rectangle pagesize) {
float width = pagesize.getWidth();
float height = pagesize.getHeight();
return new Rectangle(width, height / 2);
}
In this example, we ask the PdfReader instance for the page size of the first page and we create a new rectangle with the same width and only half the height.
We then import each page in the document, and we add it twice on different pages:
once on the odd pages with a negative y value to show the upper half of the original page,
once on the even pages with y = 0 to show the lower half of the original page.
As every page in the original document can have a different size, we may need to change the page size for every new couple of pages.
This example cuts a page in two with an upper part and a lower part. Use simple math and you can adapt the example to cut it in two with a left and a right part. This is done in the example TileInTwo2:
For instance:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
// step 1
Rectangle mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(1)));
Document document = new Document(mediabox);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte content = writer.getDirectContent();
PdfImportedPage page;
int i = 1;
while (true) {
page = writer.getImportedPage(reader, i);
content.addTemplate(page, 0, 0);
document.newPage();
content.addTemplate(page, -mediabox.getWidth(), 0);
if (++i > n)
break;
mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(i)));
document.setPageSize(mediabox);
document.newPage();
}
// step 5
document.close();
reader.close();
}
public Rectangle getHalfPageSize(Rectangle pagesize) {
float width = pagesize.getWidth();
float height = pagesize.getHeight();
return new Rectangle(width / 2, height);
}
You should have no problem to adapt this example so that different PDF documents are created instead of the one containing the left and right part. If that is problematic for you, please post another question.
Hi i am using below code. When i upload some of PDF's which contain some content and after uploading, their is no content on uploaded PDF. Uploaded PDf is blank. I am using below method of ItextSharp for change the version of Orginial PDF to Defined Version.
private int WriteCompatiblePdf(string fileName, FileUpload filePath)
{
string sNewPdf = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["InterfaxPath"]) + fileName;
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(filePath.FileBytes);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
// step 1: creation of a document-object
iTextSharp.text.Document document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, new FileStream(sNewPdf, FileMode.Create, FileAccess.ReadWrite));
//write pdf that pdfsharp can understand
writer.SetPdfVersion(iTextSharp.text.pdf.PdfWriter.PDF_VERSION_1_4);
// step 3: we open the document
document.Open();
iTextSharp.text.pdf.PdfContentByte cb = writer.DirectContent;
iTextSharp.text.pdf.PdfImportedPage page;
int rotation;
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
// step 5: we close the document
document.Close();
return n;
}
Any recommendations?
The OP provided a sample "blank" file.
As it turns out, this "blank" file does contain the desired content, it merely is way off-page.
Details
The pages of the document have this media box definition:
/MediaBox[0 7072 612 7864]
Thus, the visible area has x coordinates in 0..612 and y coordinates in 7072..7864. When adding the imported page contents, though, the OP explicitly anchors them explicitly at the coordinates 0,0:
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
The contents of the former page, therefore, are added in the area with y coordinates 0..792. So, they are not visible.
Resolutions
There are different ways to resolve this issue:
add the contents at the position with the correct coordinates, i.e. use
cb.AddTemplate(page, 1f, 0, 0, 1f, x, y);
where x and y are Left and Bottom of reader.GetPageSizeWithRotation(1) (a Rectangle); or
normalize the page size rectangle for the Document constructor to be based in 0,0; or
use a PdfStamper with the PdfReader instead of the PdfWriter and use it to select the desired version.
it's because you're not set any text to be written in the PDF. this is a simple example how to write text
string newFile = #"C:\the path\file.pdf";
Document doc = new Document(iTextSharp.text.PageSize.A4, 10, 10, 42, 35);
PdfWriter write = PdfWriter.GetInstance(doc, new FileStream(newFile,
FileMode.Create));
doc.Open(); // open the connection
Paragraph p1 = new Paragraph("text to be displayed in the first paragraph");
doc.Add(p1); // close the connection
this link will tell you the proper way to write from iTextSharp more advanced
All,
I am trying to add image watermark in pdf using itextsharp. Watermark is appearing on all the pages as expected but with ones that already have image. I want my watermarking image to come on top of the existing image on the pdf.
I am using following code to add image
using (Stream output = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, output))
{
for (int pageIndex = 1; pageIndex <= pdfReader.NumberOfPages; pageIndex++)
{
pdfStamper.FormFlattening = false;
iTextSharp.text.Rectangle pageRectangle = pdfReader.GetPageSizeWithRotation(pageIndex);
PdfContentByte pdfData = pdfStamper.GetUnderContent(pageIndex);
pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 10);
PdfGState graphicsState = new PdfGState();
graphicsState.FillOpacity = 0.4F;
pdfData.SetGState(graphicsState);
pdfData.BeginText();
iTextSharp.text.Image jpeg = iTextSharp.text.Image.GetInstance(wtrmrkimg, BaseColor.GREEN);
float width = pageRectangle.Width;
float height = pageRectangle.Height;
jpeg.ScaleToFit(width, height);
jpeg.SetAbsolutePosition(width / 2 - jpeg.Width / 2, height / 2 - jpeg.Height / 2);
jpeg.SetAbsolutePosition(50, 50);
jpeg.Rotation = 45;
pdfData.AddImage(jpeg);
pdfData.EndText();
}
pdfStamper.Close();
}
output.Close();
output.Dispose();
}
I am attaching output of the current code also :
I just got it working by replacing
PdfContentByte pdfData = pdfStamper.GetUnderContent(pageIndex);
with
PdfContentByte pdfData = pdfStamper.GetOverContent(pageIndex);
Replace
jpeg.SetAbsolutePosition(width / 2 - jpeg.Width / 2, height / 2 - jpeg.Height / 2);
With
jpeg.SetAbsolutePosition(width / 2 - jpeg.ScaledWidth / 2, height / 2 - jpeg.ScaledHeight / 2);
and remove
jpeg.SetAbsolutePosition(50, 50);
to get watermark centered