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
Related
How do you change the DocumentRenderer in iText7 and continue on the corect position? I need some paragraphs to be rendered in 2 columns, and then normal text.
This is what I have, but it not works as expected:
using (MemoryStream oDocumentStream = new MemoryStream())
{
using (PdfWriter oDocumentWriter = new PdfWriter(oDocumentStream).SetSmartMode(true))
{
PdfDocument pdfDocument = new PdfDocument(oDocumentWriter);
Document document = new Document(pdfDocument);
float offSet = 60;
float columnWidth = (PageSize.A4.GetWidth() - offSet * 2 + 10) / 2;
float columnHeight = PageSize.A4.GetHeight() - offSet * 2;
//Define column areas
Rectangle[] columns = new Rectangle[]
{
new Rectangle(offSet - 5, offSet, columnWidth, columnHeight),
new Rectangle(offSet + columnWidth, offSet, columnWidth, columnHeight)
};
document.SetRenderer(new ColumnDocumentRenderer(document, columns)); //First renderer
document.Add(*myparagraph*);
document.SetRenderer(new iText.Layout.Renderer.DocumentRenderer(document)); //Second renderer
document.Add(*myparagraph*);
document.Close();
}
oPdfFile = oDocumentStream.ToArray();
}
The issue with this approach is that the second renderer don't continue where the first renderer ended, therefore they overlap, as you can see in this image:
I am creating a PDF in MVC project using iTextSharp on .NET platform. I am sending a HTML div in "Download PDF" function and adding image from c# code using iTextSharp classes, but now I want to add an Image on 3rd page but unfortunately I am unable to do that. Please help me.
Please find the below code that I wrote for adding image on first page, last page and a loop for adding image on each page... (BUT I CAN NOT ADD AN IMAGE ONLY ON 3RD PAGE)...
using (MemoryStream stream = new System.IO.MemoryStream())
{
string Grid = GridHtml.Replace("<br>", "\n\r");
StringReader sr = new StringReader(Grid);
iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(PageSize.A4, 10f, 10f, 100f, 0f);
pdfDoc.SetMargins(50f, 50f, 90f, 0f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
MyEvent events = new MyEvent();
writer.PageEvent = events;
pdfDoc.Open();
string imageURL1 = Server.MapPath("~/UploadedFiles/Calibehr.png");
iTextSharp.text.Image jpg12 = iTextSharp.text.Image.GetInstance(imageURL1);
////Resize image depend upon your need
jpg12.ScaleToFit(140f, 120f);
jpg12.SpacingBefore = 10f;
//////Give some space after the image
jpg12.SpacingAfter = 1f;
jpg12.Alignment = Element.ALIGN_CENTER;
jpg12.SetAbsolutePosition(40, 750);
pdfDoc.Add(jpg12);
if ((fc["hdnFormatType"] != "ManageService"))
{
string imageURL3 = Server.MapPath("~/UploadedFiles/Swati-Sign.png");
iTextSharp.text.Image jpgSign = iTextSharp.text.Image.GetInstance(imageURL3);
////Resize image depend upon your need
jpgSign.ScaleToFit(140f, 120f);
jpgSign.SpacingBefore = 10f;
//////Give some space after the image
jpgSign.SpacingAfter = 1f;
jpgSign.Alignment = Element.ALIGN_LEFT;
jpgSign.SetAbsolutePosition(40, 160);
//jpg12.
pdfDoc.Add(jpgSign);
}
string imageURL2 = Server.MapPath("~/UploadedFiles/footer.jpg");
iTextSharp.text.Image jpgFooter = iTextSharp.text.Image.GetInstance(imageURL2);
////Resize image depend upon your need
jpgFooter.ScaleToFit(140f, 120f);
jpgFooter.SpacingBefore = 10f;
//////Give some space after the image
jpgFooter.SpacingAfter = 1f;
jpgFooter.Alignment = Element.ALIGN_LEFT;
jpgFooter.ScaleAbsoluteWidth(510);
jpgFooter.ScaleAbsoluteHeight(70);
jpgFooter.SetAbsolutePosition(40, 0);
//jpg12.
pdfDoc.Add(jpgFooter);
XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
string imageURL4 = Server.MapPath("~/UploadedFiles/Swati-Sign.png");
iTextSharp.text.Image jpgFooterSign = iTextSharp.text.Image.GetInstance(imageURL4);
////Resize image depend upon your need
jpgFooterSign.ScaleToFit(140f, 120f);
jpgFooterSign.SpacingBefore = 10f;
//////Give some space after the image
jpgFooterSign.SpacingAfter = 1f;
jpgFooterSign.Alignment = Element.ALIGN_LEFT;
if ((fc["hdnFormatType"] == "ManageService"))
{
jpgFooterSign.SetAbsolutePosition(20, 150);
}
else
{
jpgFooterSign.SetAbsolutePosition(20, 450);
}
writer.DirectContent.AddImage(jpgFooterSign, false);
pdfDoc.Close();
return File(stream.ToArray(), "application/pdf", CandName + "-" + empId + ".pdf");
}
}
Try this one:- set positions also what you want.
public void AddImage(int pageNumber)
{
if (pageNumber > 0)
{
string pdfTemplate =
#"D:\Input.pdf";
string newFile = #"D:\Output.pdf";
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(
newFile, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
string chartLoc = string.Empty;
chartLoc = #"C:\img.png";
iTextSharp.text.Image chartImg = iTextSharp.text.Image.GetInstance(chartLoc);
iTextSharp.text.pdf.PdfContentByte underContent;
iTextSharp.text.Rectangle rect;
try
{
Single X, Y; int pageCount = 0;
rect = pdfReader.GetPageSizeWithRotation(1);
if (chartImg.Width > rect.Width || chartImg.Height > rect.Height)
{
chartImg.ScaleToFit(rect.Width, rect.Height);
X = (rect.Width - chartImg.ScaledWidth) / 2;
Y = (rect.Height - chartImg.ScaledHeight) / 2;
}
else
{
X = (rect.Width - chartImg.Width) / 2;
Y = (rect.Height - chartImg.Height) / 2;
}
chartImg.SetAbsolutePosition(X, Y);
pageCount = pdfReader.NumberOfPages;
//Below to add image to all pages
//for (int i = 1; i < pageCount; i++)
//{
// underContent = pdfStamper.GetOverContent(i);//.GetUnderContent(i);
// underContent.AddImage(chartImg);
//}
if (pageCount >= pageNumber)
{
underContent = pdfStamper.GetOverContent(pageNumber);//.GetUnderContent(i);
underContent.AddImage(chartImg);
}
pdfStamper.Close();
pdfReader.Close();
}
catch (Exception ex)
{
throw ex;
}
}
}
I am trying to create a report from my windows form as a pdf, So i used the itextsharp library to create the pdf like that:
Document reportaspdf = new Document(iTextSharp.text.PageSize.LETTER, 10f, 10f, 10f, 0f);
PdfWriter writer = PdfWriter.GetInstance(reportaspdf, new FileStream(sfd.FileName, FileMode.Create));
reportaspdf.Open();
#region Design border
var content = writer.DirectContent;
var pageBorderRect = new iTextSharp.text.Rectangle(reportaspdf.PageSize);
pageBorderRect.Left += reportaspdf.LeftMargin;
pageBorderRect.Right -= reportaspdf.RightMargin;
pageBorderRect.Top -= reportaspdf.TopMargin;
pageBorderRect.Bottom += reportaspdf.BottomMargin;
content.SetColorStroke(BaseColor.BLACK);
content.Rectangle(pageBorderRect.Left, pageBorderRect.Bottom, pageBorderRect.Width, pageBorderRect.Height);
content.Stroke();
#endregion
//Add Text
var TitleFont = FontFactory.GetFont("Segoe UI", 50.0f, BaseColor.BLACK);
var SubtitleFont = FontFactory.GetFont("Segoe UI", 30.0f, BaseColor.BLACK);
var DescribtionFont = FontFactory.GetFont("Segoe UI", 20.0f, BaseColor.ORANGE);
var p1 = new Paragraph("Final Report", TitleFont);
p1.Alignment = Element.ALIGN_CENTER;
reportaspdf.Add(new Paragraph(p1));
#region add originalimg
var Describitiontext = new Paragraph("Original Image", DescribtionFont);
Describitiontext.Alignment = Element.ALIGN_CENTER;
Describitiontext.SpacingBefore = 20;
reportaspdf.Add(new Paragraph(Describitiontext));
iTextSharp.text.Image orignamIMG = iTextSharp.text.Image.GetInstance(OrignalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
orignamIMG.Alignment = Element.ALIGN_CENTER;
reportaspdf.Add(orignamIMG);
#endregion
Until now everything is perfect but after adding another images and text they have been added under the previous images but i want to structure my report as every 2 image at the same level and so on
So, How can i added more than one item at the same level ?
The second thing is
when i take a screen capture from panel, the width of image became larger than the document width so i use this function to resize the image before adding it to the pdf document but it's resolution become so poor,
So, How can i resize image without loosing the quality ?
public Bitmap Resizeimage(Bitmap image, int maxWidth, int maxHeight)
{
// Get the image's original width and height
int originalWidth = image.Width;
int originalHeight = image.Height;
// To preserve the aspect ratio
float ratioX = (float)maxWidth / (float)originalWidth;
float ratioY = (float)maxHeight / (float)originalHeight;
ratio = Math.Min(ratioX, ratioY);
// New width and height based on aspect ratio
int newWidth = (int)(originalWidth * ratio);
int newHeight = (int)(originalHeight * ratio);
// Convert other formats (including CMYK) to RGB.
Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);
// Draws the image in the specified size with quality mode set to HighQuality
using (Graphics graphics = Graphics.FromImage(newImage))
{
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
I have a PDF file and I want to add a simple number on each page.
Here is my code:
reader = new PdfReader(fileOut);
Document final = new Document(reader.GetPageSize(1));
PdfWriter w = PdfWriter.GetInstance(final, new FileStream(finalFile, FileMode.Create, FileAccess.Write));
w.SetFullCompression();
final.Open();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
final.NewPage();
PdfContentByte cb = w.DirectContent;
ControlNumberTimes(cb, "C"+i, 560, 725, 270, Element.ALIGN_LEFT);
cb.AddTemplate(w.GetImportedPage(reader, i), 0, 0);
}
final.Close();
reader.Close();
private static void ControlNumberTimes( PdfContentByte cb1, string control, int x, int y, int rotation, int allign )
{
cb1.BeginText();
cb1.SetColorFill(BaseColor.BLACK);
cb1.SetFontAndSize(BaseFont.CreateFont("C:\\windows\\Fonts\\times.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 7.5f);
cb1.ShowTextAligned(allign, control, x, y, rotation);
cb1.EndText();
}
Before adding this text, PDF file size is 3.6 Mb, after the size is 11 Mb.
What I am doing wrong?
This is my code now:
string finalFile = System.IO.Path.GetDirectoryName(fileOut) + "\\" +
System.IO.Path.GetFileNameWithoutExtension(fileOut) + "_num.pdf";
reader = new PdfReader(fileOut);
using (FileStream fs = new FileStream(finalFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
int pageCount = reader.NumberOfPages;
for (int i = 1; i <= pageCount; i++)
{
ColumnText.ShowTextAligned(stamper.GetUnderContent(i), Element.ALIGN_CENTER, new Phrase(
$"C{i}"), 560, 725, 0);
}
}
}
The pdf file I can't share due of the confidential information.
This is completely wrong:
reader = new PdfReader(fileOut);
Document final = new Document(reader.GetPageSize(1));
PdfWriter w = PdfWriter.GetInstance(final, new FileStream(finalFile, FileMode.Create, FileAccess.Write));
w.SetFullCompression();
final.Open();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
final.NewPage();
PdfContentByte cb = w.DirectContent;
ControlNumberTimes(cb, "C"+i, 560, 725, 270, Element.ALIGN_LEFT);
cb.AddTemplate(w.GetImportedPage(reader, i), 0, 0);
}
final.Close();
Saying "I am copying a file using Document, PdfWriter, PdfImportedPage and AddTemplate, why does my file size increase?" is like asking "I've stabbed myself in the belly with a sharp knife, why do I bleed?"
If you want to add page numbers to an existing document, you have to use PdfStamper as explained in chapter 6 of my book.
You want to manipulate an existing PDF, more specifically, you want to add page numbers in the footer. That is done like this:
PdfReader reader = new PdfReader(outputFile);
using (FileStream fs = new FileStream(secondFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (PdfStamper stamper = new PdfStamper(reader, fs)) {
int PageCount = reader.NumberOfPages;
for (int i = 1; i <= PageCount; i++) {
ColumnText.ShowTextAligned(stamper.GetOverContent(i), Element.ALIGN_CENTER, new Phrase(String.Format("Page {0} of {1}", i, PageCount)), 560, 725, 270);
}
}
}
Some remarks:
You are using absolute coordinates (X = 560, Y = 725). It would be better to use coordinates relative to the page size as described in the official documentation: How to position text relative to page?
You are using BeginText() ... EndText(), but it might be easier for you to use ColumnText.ShowTextAligned().
You think you are using a font that isn't embedded when you create a BaseFont like this BaseFont.CreateFont("C:\\windows\\Fonts\\times.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED). That's not true. As documented, BaseFont.NOT_EMBEDDED is ignored when using BaseFont.IDENTITY_H. See Why is iText embedding a font even when I specify not to embed? If a small file size is desired, I suggest you don't embed the font.
The main problem with your code, is the fact that you aren't manipulating a file the correct way. I think this is caused by the fact that you copy/pasted your code from a badly written tutorial. Please don't copy code from people who don't know what they're doing.
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);