I am creating pdf using itextsharp. Now I want to add watermark on each pages I tried method on
public override void OnStartPage(PdfWriter wr, iTextSharp.text.Document doc)
Now watermark is coming but if pdf page containing image then its hiding watermark
public class itsevent : PdfPageEventHelper
{
string watermarkText = string.Empty;
public itsevent(string watermark)
{
watermarkText = watermark;
}
public override void OnStartPage(PdfWriter wr, iTextSharp.text.Document doc)
{
float fontSize = 80;
float xPosition = 300;
float yPosition = 300;
float angle = 45;
PdfContentByte u = wr.DirectContentUnder;
PdfGState gs = new PdfGState();
u.SaveState();
u.SetGState(gs);
BaseFont baseFont =BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
u.BeginText();
u.SetColorFill(iTextSharp.text.pdf.CMYKColor.LIGHT_GRAY);
u.SetFontAndSize(baseFont, fontSize);
u.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
u.EndText();
under.RestoreState();
}
}
itsevent ev = new itsevent("watermark");
pdfW.PageEvent = ev;
doc.Open();
Which PdfContentByte to use
You use wr.DirectContentUnder which is for adding content under the normally added content:
PdfContentByte u = wr.DirectContentUnder;
Thus, obviously an image in the normal content will cover the watersign. Use wr.DirectContent instead.
Which page event to use
You are adding the watermark in OnStartPage; iText developers recommend against doing so. Instead do that in OnEndPage.
How to improve the looks
You might want to apply transparency by setting the fill opacity of PdfGState gs.
Try using GetOverContext() to get the image
https://simpledotnetsolutions.wordpress.com/2012/04/08/itextsharp-few-c-examples/
Related
i want know how can i append the custom border to the iTextSharp pdfdcell.
like
the problem is that i cant find a way to add border with 2 line.
i can only create a normal bottom border in the pdfdcell by
PdfPCell tmp = new PdfPCell(new Phrase(c));
tmp.HorizontalAlignment = Element.ALIGN_RIGHT;
tmp.Border = c.borderPosition;
tmp.BorderWidth = c.borderWidth;
pt.AddCell(tmp);
so the result is something like this
but i need to add one more line under the border.
Since I am using C# and iTextSharp and the comment is only showing the solution on Java.
I have implemented the similar thing to solve the issue.
The basic fact is that iTextSharp didn't support custom border, but it allows you to draw things on the PDF. Thus the objective is to draw a doubleline at the bottom of the cell.
hide existing border
find out the exact position of the cell
draw lines
the trick is that implementing the CellEvent on the cell, within the cellevent it gave us the exact position of the cell, thus we draw things easily.
below is the code which working in my C# project
public function void DrawACell_With_DOUBLELINE_BOTTOM_BORDER(Document doc, PdfWriter writer){
PdfPTable pt = new PdfPTable(new float[]{1});
Chunk c = new Chunk("A Cell with doubleline bottom border");
int padding = 3;
PdfPCell_DoubleLine cell = new PdfPCell_DoubleLine(PdfPTable pt,new Phrase(c), writer, padding);
pt.AddCell(cell);
doc.Add(pt);
}
public class PdfPCell_DoubleLine : PdfPCell
{
public PdfPCell_DoubleLine(Phrase phrase, PdfWriter writer, int padding) : base(phrase)
{
this.HorizontalAlignment = Element.ALIGN_RIGHT;
//1. hide existing border
this.Border = Rectangle.NO_BORDER;
//2. find out the exact position of the cell
this.CellEvent = new DLineCell(writer, padding);
}
public class DLineCell : IPdfPCellEvent
{
public PdfWriter writer { get; set; }
public int padding { get; set; }
public DLineCell(PdfWriter writer, int padding)
{
this.writer = writer;
this.padding = padding;
}
public void CellLayout(PdfPCell cell, iTextSharp.text.Rectangle rect, PdfContentByte[] canvases)
{
//draw line 1
PdfContentByte cb = writer.DirectContent;
cb.MoveTo(rect.GetLeft(0), rect.GetBottom(0) - padding);
cb.LineTo(rect.GetRight(0), rect.GetBottom(0) - padding);
//draw line 2
cb.MoveTo(rect.GetLeft(0), rect.GetBottom(0) - padding - 2);
cb.LineTo(rect.GetRight(0), rect.GetBottom(0) - padding - 2);
cb.Stroke();
}
}
}
I am trying to render a PDF with a grid of images, using iTextSharp (v5.5.10). The images will all have the same dimensions and should be evenly distributed on one page.
However, with the code mentioned below, I'm having difficulty in setting the appropriate margins, or spacing between the cells.
Visually this means that the expected result is this:
The yellow highlighted lines are the problem where I'm getting the following result instead:
Notice how there are no spaces between the images? This is based on my following code:
public void CreateGridOfImages(string outputFilePath)
{
// note: these constants are in millimeters (mm),
// which are converted using the ToPoints() helper later on
const float spacingBetweenCells = 7;
const float imageWidth = 80;
const float imageHeight = 80;
const string[] images = new [] { "a.jpg", "b.jpg", "c.jpg" };
using (var stream = new FileStream(outputFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var document = new iTextSharp.text.Document(PageSize.B2, 0f, 0f, 0f, 0f);
var writer = PdfWriter.GetInstance(document, stream);
try
{
document.Open();
var table = new PdfPTable(5);
table.DefaultCell.Border = Rectangle.NO_BORDER;
foreach (var imagePath in images)
{
var img = iTextSharp.text.Image.GetInstance(imagePath);
img.ScaleToFit(ToPoints(imageWidth), ToPoints(imageHeight));
var cell = new PdfPCell();
// THIS IS THE PROBLEM... HOW TO SET IMAGE SPACING?
var cellMargin = ToPoints(spacingBetweenCells);
cell.AddElement(img);
table.AddCell(cell);
}
document.Add(table);
}
catch (Exception ex)
{
throw ex;
}
finally
{
document.Close();
}
}
}
private float ToPoints(float millimeters)
{
// converts millimeters to points
return iTextSharp.text.Utilities.MillimetersToPoints(millimeters);
}
Now this seems trivial. And it problably is, but I've tried several options and could none of them to work properly (or at all):
Adding Paragraph() objects with paddings between each
Adding Padding to PdfPCell does not seem to work for me
Looked into custom IPdfPCellEvent samples
Absolutely positioning the images alltogether (forgetting the PdfPTable)
My hunch is that the IPdfPCellEvent seems the right approach. But all the iText options and variations are simply overwhelming.
Summarized, does anyone know how can I properly set the margins/spacing between the cells?
I assume you want to have the second table in this image:
The only way to create white spacing between cells in an iText table is to set the relevant borders to the background colour and play with the padding of the cell. My pivotal code for creating the cells is:
for(int i = 0; i < nrCols* nrRows;i++) {
var img = Image.GetInstance(imagePath);
img.ScaleToFit(ToPoints(imageWidth), ToPoints(imageHeight));
//Create cell
var imageCell = new PdfPCell();
imageCell.Image = img;
imageCell.Border = Rectangle.BOX;
imageCell.BorderColor = useColor? BaseColor.YELLOW : BaseColor.WHITE;
//Play with this value to change the spacing
imageCell.Padding = ToPoints(spacingBetweenCells/2);
imageCell.HorizontalAlignment = Element.ALIGN_CENTER;
grid.AddCell(imageCell);
}
As to why adding padding to the PdfPCell didn't seem to worrk:
The reason why borders are still drawn in your example, despite
table.DefaultCell.Border = Rectangle.NO_BORDER;
Is because you never use the default cell because you create a custom one with var cell = new PdfPCell(); and pass the custom one to table.AddCell(cell);. If you'd have used table.addCell(img), the border would not have been there (although your padding would still not be your desired spacing, since it isn't set on the default cell).
Can't seem to find much out there for this. I've a PDF, onto which I'd like to overlay an image of an electronic signature. Any suggestions on how to accomplish that using PDFSharp?
Thanks
Try the following
private void GeneratePDF(string filename, string imageLoc)
{
PdfDocument document = new PdfDocument();
// Create an empty page or load existing
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
DrawImage(gfx, imageLoc, 50, 50, 250, 250);
// Save and start View
document.Save(filename);
Process.Start(filename);
}
void DrawImage(XGraphics gfx, string jpegSamplePath, int x, int y, int width, int height)
{
XImage image = XImage.FromFile(jpegSamplePath);
gfx.DrawImage(image, x, y, width, height);
}
This will generate a new PDF with the specified image near the top of the page. If you need to use an existing document change the PdfDocument constructor to
PdfDocument document = new PdfDocument(filename);
where filename is the name of the file to load and change the PdfPage line to
PdfPage page = document.Pages[pageNum];
where pageNum is the number of the page on which you need to add the image.
After that, it just a matter of getting the positioning on the page by altering the parameters for DrawImage to suit.
DrawImage(gfx, imageLoc, 50, 50, 250, 250);
Good luck!
This will help you:
PdfDocument document = pdf;
// Create a new page
PdfPage page = document.Pages[0];
page.Orientation = PageOrientation.Portrait;
XGraphics gfx = XGraphics.FromPdfPage(page, XPageDirection.Downwards);
// Draw background
gfx.DrawImage(XImage.FromFile("pdf_overlay.png"), 0, 0);
Just add the path to the image you want, and specify the position of the image.
To roughly maintain the aspect ratio, I used #Kami's answer and "roughly" centered it.
The assumption made is that the pdf width is 600 and pdf height is 800, we will make use of the middle 500 and 700 of the page only, leaving the 4 sides have at least 50 in length as margin.
public static void GeneratePdf(string outputPath, string inputPath)
{
PdfSharp.Pdf.PdfDocument document = new PdfSharp.Pdf.PdfDocument();
// Create an empty page or load existing
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
DrawImage(gfx, inputPath);
// Save and start View
document.Save(outputPath);
Process.Start(outputPath);
}
public static void DrawImage(XGraphics gfx, string imagePath)
{
XImage image = XImage.FromFile(imagePath);
var imageHeight = image.PixelHeight;
var imageWidth = image.PixelWidth;
int height;
int width;
int x;
int y;
width = 500;
height = (int) Math.Ceiling((double) width * imageHeight / imageWidth);
x = 50;
y = (int) Math.Ceiling((800 - height) / 2.0);
if(height > 700)
{
height = 700;
width = (int) Math.Ceiling(imageWidth * (double) height / imageHeight);
y = 50;
x = (int) Math.Ceiling((600 - width) / 2.0);
}
gfx.DrawImage(image, x, y, width, height);
}
I am using itext sharp for creating reports in PDF format.
I want page borders. I tried some ways. I am not successful.
How can I get a page border for top, bottom, left, right using iText for .NET?
I added one image 1. I want borders like described in the image.
You can try this code for adding the image for the header manually.
//Step 1: Add the Image file
strImgPath is refer the directory Info..
Image imgLogo = Image.GetInstance(strImgPath.ToString()+"\\abcdur compe.Jpg");
imgLogo.Alignment = Image.ALIGN_CENTER;
imgLogo.ScalePercent(50f);
// Step 2:
Add this ImgLogo to the PdfPTable by use of this
PdfPCell pdfcellImage = new PdfPCell(imgLogo, true);
pdfcellImage.FixedHeight = 40f;
pdfcellImage.HorizontalAlignment = Element.ALIGN_CENTER;
pdfcellImage.VerticalAlignment = Element.ALIGN_CENTER;
pdfcellImage.Border = Rectangle.NO_BORDER;
pdfcellImage.Border = Rectangle.NO_BORDER;
pdftblImage.AddCell(pdfcellImage);
// Step 3:
Create Chunck to add Text for address or others
fntBoldComHd is a Base Font Library Object
Chunk chnCompany = new Chunk("Your CompanyName\nAddress", fntBoldComHd);
//Step 4:
Create Phrase For add the Chunks and PdfPTables
Phrase phHeader = new Phrase();
phHeader.Add(pdftblImage);
phHeader.Add(chnCompany);
// Step 5:
Assign the Phrase to PDF Header
HeaderFooter header = new HeaderFooter(phHeader, false);
header.Border = Rectangle.NO_BORDER;
header.Alignment = Element.ALIGN_CENTER;
docPDF.Header = header;
I am using one hacky way of workaround but it will create the border.Use this method.
private void CreateBorder(PdfContentByte cb, PdfWriter writer, Document doc)
{
iTextSharp.text.Rectangle r = doc.PageSize;
float left = r.Left + 30;
float right = r.Right - 30;
float top = r.Top - 30;
float bottom = r.Bottom + 30;
float width = right - left;
float height = top - bottom;
PdfPTable tab = new PdfPTable(1);
tab.TotalWidth = width;
tab.LockedWidth = true;
PdfPCell t = new PdfPCell(new Phrase(String.Empty));
t.BackgroundColor = new BaseColor(250, 235, 215);
t.FixedHeight = height;
t.BorderWidth = 3;
tab.AddCell(t);
Paragraph pa = new Paragraph();
pa.Add(tab);
float h = tab.TotalHeight;
PdfTemplate temp = cb.CreateTemplate(tab.TotalWidth, h);
tab.WriteSelectedRows(0, -1, 0.0F, h, temp);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(temp);
img.SetAbsolutePosition(30, 30);
cb.AddImage(img);
}
If u want one more section for header create table width two rows.I hope this helps.
Are you referring to the document margins? If yes, use the Document object's ctor to specify them:
public Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom);
I am trying to programmatically create a number of PDF documents with a watermark on each page using itextsharp (a C# port of Java's itext).
I am able to do this after the document has been created using a PdfStamper. However this seems to involve re-opening the document reading it and then creating a new document with the watermark on each page.
Is there a way of doing this during document creation?
After digging into it I found the best way was to add the watermark to each page as it was created. To do this I created a new class and implemented the IPdfPageEvent interface as follows:
class PdfWriterEvents : IPdfPageEvent
{
string watermarkText = string.Empty;
public PdfWriterEvents(string watermark)
{
watermarkText = watermark;
}
public void OnOpenDocument(PdfWriter writer, Document document) { }
public void OnCloseDocument(PdfWriter writer, Document document) { }
public void OnStartPage(PdfWriter writer, Document document) {
float fontSize = 80;
float xPosition = 300;
float yPosition = 400;
float angle = 45;
try
{
PdfContentByte under = writer.DirectContentUnder;
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
under.BeginText();
under.SetColorFill(BaseColor.LIGHT_GRAY);
under.SetFontAndSize(baseFont, fontSize);
under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
under.EndText();
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
public void OnEndPage(PdfWriter writer, Document document) { }
public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }
}
}
This object is registered to handle the events as follows:
PdfWriter docWriter = PdfWriter.GetInstance(document, new FileStream(outputLocation, FileMode.Create));
PdfWriterEvents writerEvent = new PdfWriterEvents(watermark);
docWriter.PageEvent = writerEvent;
Although Tim's solution seems very nice, I have managed to do the same thing (I believe) using the following code (perhaps iTextSharp was improved a bit since then...):
private byte[] AddWatermark(byte[] bytes, BaseFont bf)
{
using(var ms = new MemoryStream(10 * 1024))
{
using(var reader = new PdfReader(bytes))
using(var stamper = new PdfStamper(reader, ms))
{
int times = reader.NumberOfPages;
for (int i = 1; i <= times; i++)
{
var dc = stamper.GetOverContent(i);
PdfHelper.AddWaterMark(dc, AppName, bf, 48, 35, new BaseColor(70, 70, 255), reader.GetPageSizeWithRotation(i));
}
stamper.Close();
}
return ms.ToArray();
}
}
public static void AddWaterMark(PdfContentByte dc, string text, BaseFont font, float fontSize, float angle, BaseColor color, Rectangle realPageSize, Rectangle rect = null)
{
var gstate = new PdfGState { FillOpacity = 0.1f, StrokeOpacity = 0.3f };
dc.SaveState();
dc.SetGState(gstate);
dc.SetColorFill(color);
dc.BeginText();
dc.SetFontAndSize(font, fontSize);
var ps = rect ?? realPageSize; /*dc.PdfDocument.PageSize is not always correct*/
var x = (ps.Right + ps.Left) / 2;
var y = (ps.Bottom + ps.Top) / 2;
dc.ShowTextAligned(Element.ALIGN_CENTER, text, x, y, angle);
dc.EndText();
dc.RestoreState();
}
This will add a watermark on all pages of a PDF document that is provided as a byte array.
(You don't need to do it while creating the PDF.)
It seems working for both landscape and portrait and it probably works for documents with mixed orientations.
Cheers! :)
string WatermarkLocation = "D:\\Images\\superseded.png";
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(125, 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.GetOverContent(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);
I used the first solution. I was having trouble getting it to work at first. I getting green underlines under all of my public voids saying that it was going to hide some inherit member.
Basically I realized that I already had added a PagePageEventHelper and I basically just cut out the code for the OnStartPage. ALSO! For some reason I had to make all of my public void's public override void.
public override void OnStartPage(PdfWriter writer, Document document)
{
if (condition)
{
string watermarkText = "-whatever you want your watermark to say-";
float fontSize = 80;
float xPosition = 300;
float yPosition = 400;
float angle = 45;
try
{
PdfContentByte under = writer.DirectContentUnder;
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
under.BeginText();
under.SetColorFill(iTextSharp.text.pdf.CMYKColor.LIGHT_GRAY);
under.SetFontAndSize(baseFont, fontSize);
under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
under.EndText();
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
}
Can't you just lay down the watermark on each page after you've made it?
Yes, the Watermark class seems to be no more - odd. However in the process of converting to iTextSharp 5.3, I found a simple way to add a watermark to a new document.
MemoryStream mem = new MemoryStream();
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, mem);
PdfContentByte cb = writer.DirectContent;
document.Open();
document.NewPage();
Image watermark = Image.GetInstance(WATERMARK_URI);
watermark.SetAbsolutePosition(80, 200);
document.Add(watermark);
BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
...
cb.EndText();
document.Close();
In iTextSharp you should be able to programmatically add a watermark e.g.
Watermark watermark = new Watermark(Image.getInstance("watermark.jpg"), 200, 420);
document.Add(watermark);