c# itextsharp PDF creation with watermark on each page
我正在尝试使用itextsharp(Java的itext的C#端口)以编程方式在每个页面上创建许多带水印的PDF文档。
使用PdfStamper创建文档后,我可以执行此操作。但是,这似乎涉及重新打开读取文档的文档,然后在每页上创建带有水印的新文档。
在文档创建期间是否可以执行此操作?
深入研究它之后,我发现最好的方法是在创建每个页面时将水印添加到每个页面。为此,我创建了一个新类并实现IPdfPageEvent接口,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 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) { } } } |
注册此对象以处理事件,如下所示:
1 2 3 |
尽管Tim的解决方案看起来非常不错,但我已经设法使用以下代码(也许自那时以来iTextSharp有所改进...)来做相同的事情(我相信):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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(); } |
这将在以字节数组提供的PDF文档的所有页面上添加水印。
(创建PDF时不需要这样做。)
它似乎同时适用于横向和纵向,并且可能适用于混合方向的文档。
干杯! :)
我用了第一个解决方案。一开始我很难让它工作。我在所有公共空白下都显示绿色底线,表示它将隐藏一些继承成员。
基本上,我意识到我已经添加了PagePageEventHelper,而我基本上只是剪切了OnStartPage的代码。还!出于某种原因,我不得不使所有公共void的公共替代无效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); |
制作完水印后,您是否只能在每页上放下水印?
是的,水印类似乎不再存在-很奇怪。但是,在转换为iTextSharp 5.3的过程中,我发现了一种向新文档添加水印的简单方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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(); |
在iTextSharp中,您应该能够以编程方式添加水印,例如
1 2 | Watermark watermark = new Watermark(Image.getInstance("watermark.jpg"), 200, 420); document.Add(watermark); |