How to use PDF Sharp objects in my Migradoc document - watermark

I have an application that generates PDFs using the MigraDoc framework, however I have a requirement to add in a text driven watermark. I have found some examples of this being done using PDF Sharp here, however I just cant seem t be able to figure out how this will integrate with my Migradoc Document() object I am rendering.
I have the following code:
public byte[] render()
{
PdfDocument document = new PdfDocument();
CreateWaterMarks(document);
// *****************************
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = this.document;
renderer.RenderDocument();
byte[] pdfContents = null;
using (MemoryStream stream = new MemoryStream())
{
renderer.PdfDocument.Save(stream, true);
pdfContents = stream.ToArray();
}
return pdfContents;
}
This method is what is called to render the MigraDoc document and pass it out as a byte array. The second line of code in here calls the following method which is not doing what I am looking for:
void CreateWaterMarks(PdfDocument document)
{
PdfPage page = document.AddPage();
Document doc = this.document;
MigraDoc.Rendering.DocumentRenderer docRenderer = new DocumentRenderer(doc);
docRenderer.PrepareDocument();
XRect A4Rect = new XRect(0, 0, pageActiveWidth, pageActiveHeight);
int pageCount = docRenderer.FormattedDocument.PageCount;
for (int idx = 0; idx < pageCount; idx++)
{
XFont font = new XFont("Verdana", 13, XFontStyle.Bold);
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
XSize size = gfx.MeasureString("Watermark", font);
gfx.TranslateTransform(pageActiveWidth / 2, pageActiveHeight / 2);
gfx.RotateTransform(-Math.Atan(pageActiveHeight / pageActiveWidth) * 180 / Math.PI);
gfx.TranslateTransform(-pageActiveWidth / 2, -pageActiveHeight / 2);
XStringFormat format = new XStringFormat();
format.Alignment = XStringAlignment.Near;
format.LineAlignment = XLineAlignment.Near;
XBrush brush = new XSolidBrush(XColor.FromArgb(128, 255, 0, 0));
gfx.DrawString("Watermark", font, brush, new XPoint((pageActiveWidth - size.Width) / 2, (pageActiveHeight - size.Height) / 2), format);
docRenderer.RenderPage(gfx, idx + 1);
}
}
I was hoping that this would magically make these PDFSharp watermarks appear but alas I get nothing!

I have this working using the following code:
public byte[] render()
{
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = this.document;
renderer.RenderDocument();
renderer.PrepareRenderPages();
CreateWatermarks(renderer);
byte[] pdfContents = null;
using (MemoryStream stream = new MemoryStream())
{
renderer.PdfDocument.Save(stream, true);
pdfContents = stream.ToArray();
}
return pdfContents;
}
private void CreateWatermarks(PdfDocumentRenderer renderer)
{
int pages = renderer.DocumentRenderer.FormattedDocument.PageCount;
for (int i = 0; i < pages; ++i)
{
var page = renderer.PdfDocument.Pages[i];
XFont font = new XFont("Verdana", 27, XFontStyle.Bold);
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
XSize size = gfx.MeasureString("Watermark", font);
gfx.TranslateTransform(pageActiveWidth / 2, pageActiveHeight / 2);
gfx.RotateTransform(-Math.Atan(pageActiveHeight / pageActiveWidth) * 180 / Math.PI);
gfx.TranslateTransform(-pageActiveWidth / 2, -pageActiveHeight / 2);
XStringFormat format = new XStringFormat();
format.Alignment = XStringAlignment.Near;
format.LineAlignment = XLineAlignment.Near;
XBrush brush = new XSolidBrush(XColor.FromArgb(128, 255, 0, 0));
gfx.DrawString("Watermark", font, brush, new XPoint((pageActiveWidth - size.Width) / 2, (pageActiveHeight - size.Height) / 2), format);
}
}

Related

Extract the center-aligned lines from a PDF document using itext7 in C#.Net application

anybody help me extract the center-aligned lines from a PDF document using itext7 in .Net Core application.
I have written the following extraction code so far, but cannot get the lines that are center aligned. Is there any way, please help
private async Task Extruct()
{
_pdfFile = await UploadedFilesService.GetUploadedPdfById(entryId);
MemoryStream stream = new MemoryStream(_pdfFile);
using (PdfReader pdfReader = new PdfReader(stream))
{
using (PdfDocument pdfDocument = new PdfDocument(pdfReader))
{
for (int i = 1; i <= pdfDocument.GetNumberOfPages(); i++)
{
PdfPage page = pdfDocument.GetPage(i);
string pageText = PdfTextExtractor.GetTextFromPage(page);
string[] lineTexts = pageText.Split('\n');
foreach (string lineText in lineTexts)
{
float lineWidth = lineText.Length;
float pageWidth = page.GetPageSize().GetWidth();
if ((pageWidth / 2 - lineWidth * 10) > 20)
{
persons.Add(lineText);
}
}
}
extracted = true;
}
}
this.StateHasChanged();
}

Using Drawing to create a graphic verification code does not display

I am developing an API tool for generating verification codes. I use the Drawing package. I have found some methods, but why can't I generate the graphic verification codes I need? Where am I doing wrong?
public void Output(HttpResponse objHttpResponse)
{
using (Bitmap bitmap = this.GetImage())
{
if (bitmap != null)
{
using (MemoryStream ms= new MemoryStream())
{
bitmap .Save(ms, ImageFormat.Jpeg);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = "image/Jpeg";
HttpContext.Current.Response.BinaryWrite(ms.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
}
}
}
I have a complete code for generating verification code using Bitmap, you can refer to the following:
Controller:
[ApiController]
public class CaptchaController : Controller
{
[Route("get_captcha")]
public Object VerifyCode()
{
string code = "";
Bitmap bitmap = Captcha.CreateCaptcha(out code);
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.Gif);
return File(stream.ToArray(), "image/gif");
}
}
API to generate verification code:
public class Captcha
{
public static Bitmap CreateCaptcha(out string code)
{
//Create a Bitmap object and draw
Bitmap bitmap = new Bitmap(200, 60);
Graphics graph = Graphics.FromImage(bitmap);
graph.FillRectangle(new SolidBrush(Color.White), 0, 0, 200, 60);
Font font = new Font(FontFamily.GenericSerif, 48, FontStyle.Bold, GraphicsUnit.Pixel);
Random r = new Random();
string letters = "0123456789";
StringBuilder sb = new StringBuilder();
//Add random 4 numbers
for (int x = 0; x < 4; x++)
{
string letter = letters.Substring(r.Next(0, letters.Length - 1), 1);
sb.Append(letter);
graph.DrawString(letter, font, new SolidBrush(Color.Black), x * 38, r.Next(0, 15));
}
code = sb.ToString();
//Confuse the background
Pen linePen = new Pen(new SolidBrush(Color.Black), 2);
for (int x = 0; x < 6; x++)
graph.DrawLine(linePen, new Point(r.Next(0, 199), r.Next(0, 59)), new Point(r.Next(0, 199), r.Next(0, 59)));
return bitmap;
}
}
Result:

iText 7 - Add and Remove Watermark on a PDF

I would like to add and remove a watermark to a PDF using iText 7. I was able to add the watermark, but unable to remove it again. I could only find relevant code/examples related to iText 5. Any pointers appreciated, thanks.
This is how I added the Watermark (using Layers):
pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
PageSize ps = pdfDoc.GetDefaultPageSize();
for (var i = 1; i <= numberOfPages; i++)
{
PdfPage page = pdfDoc.GetPage(i);
PdfLayer layer = new PdfLayer("watermark", pdfDoc);
var canvas = new PdfCanvas(page);
var pageSize = page.GetPageSize();
var paragraph = new Paragraph(message.WatermarkText).SetFontSize(60);
paragraph.SetFontColor(Color.BLACK, 0.2f);
Canvas canvasModel;
canvas.BeginLayer(layer);
canvasModel = new Canvas(canvas, pdfDoc, ps);
canvasModel.ShowTextAligned(paragraph, pageSize.GetWidth() / 2, pageSize.GetHeight() / 2, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
canvasModel.SetFontColor(Color.GREEN, 0.2f);
canvas.EndLayer();
}
pdfDoc.Close();
This is what I have tried to remove the watermark. I want to remove it completely, not just set the layer to not display.(any sample code appreciated):
pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
IList<PdfLayer> layers = pdfDoc.GetCatalog().GetOCProperties(true).GetLayers();
for (var i = 0; i <= layers.Count; i++)
{
var t = layers[i].GetPdfObject().Get(PdfName.Name);
if (t.ToString().Equals("watermark"))
{
//Not what I want..need to remove the layer
layers[i].SetOn(false);
//This does not work...
//layers.RemoveAt(i);
}
}
pdfDoc.Close();
With help from the guys at iText I was able to solve this.
If you intend to remove the watermark later, you will need to add it as a 'PDF watermark annotation'.
To add a watermark on every page:
public void WatermarkPDF(string sourceFile, string destinationPath)
{
float watermarkTrimmingRectangleWidth = 300;
float watermarkTrimmingRectangleHeight = 300;
float formWidth = 300;
float formHeight = 300;
float formXOffset = 0;
float formYOffset = 0;
float xTranslation = 50;
float yTranslation = 25;
double rotationInRads = Math.PI / 3;
PdfFont font = PdfFontFactory.CreateFont(FontConstants.TIMES_ROMAN);
float fontSize = 50;
PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
PdfPage page = null;
for (var i = 1; i <= numberOfPages; i++)
{
page = pdfDoc.GetPage(i);
Rectangle ps = page.GetPageSize();
//Center the annotation
float bottomLeftX = ps.GetWidth() / 2 - watermarkTrimmingRectangleWidth / 2;
float bottomLeftY = ps.GetHeight() / 2 - watermarkTrimmingRectangleHeight / 2;
Rectangle watermarkTrimmingRectangle = new Rectangle(bottomLeftX, bottomLeftY, watermarkTrimmingRectangleWidth, watermarkTrimmingRectangleHeight);
PdfWatermarkAnnotation watermark = new PdfWatermarkAnnotation(watermarkTrimmingRectangle);
//Apply linear algebra rotation math
//Create identity matrix
AffineTransform transform = new AffineTransform();//No-args constructor creates the identity transform
//Apply translation
transform.Translate(xTranslation, yTranslation);
//Apply rotation
transform.Rotate(rotationInRads);
PdfFixedPrint fixedPrint = new PdfFixedPrint();
watermark.SetFixedPrint(fixedPrint);
//Create appearance
Rectangle formRectangle = new Rectangle(formXOffset, formYOffset, formWidth, formHeight);
//Observation: font XObject will be resized to fit inside the watermark rectangle
PdfFormXObject form = new PdfFormXObject(formRectangle);
PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.6f);
PdfCanvas canvas = new PdfCanvas(form, pdfDoc);
float[] transformValues = new float[6];
transform.GetMatrix(transformValues);
canvas.SaveState()
.BeginText().SetColor(Color.GRAY, true).SetExtGState(gs1)
.SetTextMatrix(transformValues[0], transformValues[1], transformValues[2], transformValues[3], transformValues[4], transformValues[5])
.SetFontAndSize(font, fontSize)
.ShowText("watermark text")
.EndText()
.RestoreState();
canvas.Release();
watermark.SetAppearance(PdfName.N, new PdfAnnotationAppearance(form.GetPdfObject()));
watermark.SetFlags(PdfAnnotation.PRINT);
page.AddAnnotation(watermark);
}
page?.Flush();
pdfDoc.Close();
}
To remove the watermark:
public void RemovetWatermarkPDF(string sourceFile, string destinationPath)
{
PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
var numberOfPages = pdfDoc.GetNumberOfPages();
for (var i = 1; i <= numberOfPages; i++)
{
// PdfAnnotation
PdfDictionary pageDict = pdfDoc.GetPage(i).GetPdfObject();
PdfArray annots = pageDict.GetAsArray(PdfName.Annots);
for (int j = 0; j < annots.Size(); j++)
{
PdfDictionary annotation = annots.GetAsDictionary(j);
if (PdfName.Watermark.Equals(annotation.GetAsName(PdfName.Subtype)))
{
annotation.Clear();
}
}
}
pdfDoc.Close();
}
What about variable length watermark text? How would you dynamically resize the rectangle to fit the text? This is not inbuilt into iText, you would need to play around with the following dimension parameters:
float watermarkTrimmingRectangleWidth = 600;
float watermarkTrimmingRectangleHeight = 600;
float formWidth = 600;
float formHeight = 600;
float formXOffset = -100;
float fontSize = 30;
For my use-case I checked the length of the watermark text and based on that adjusted the parameters accordingly eg:
if (watermarkText.Length <= 14)
{
watermarkTrimmingRectangleWidth = 200;
watermarkTrimmingRectangleHeight = 200;
formWidth = 200;
formHeight = 200;
formXOffset = 0;
fontSize = 30;
}
else if (watermarkText.Length <= 22)
{
watermarkTrimmingRectangleWidth = 300;
watermarkTrimmingRectangleHeight = 300;
formWidth = 300;
formHeight = 300;
formXOffset = 0;
fontSize = 30;
}
else if (...)
{
...
}
.
.
etc.
.
.
else if (watermarkText.Length <= 62)
{
watermarkTrimmingRectangleWidth = 600;
watermarkTrimmingRectangleHeight = 600;
formWidth = 600;
formHeight = 600;
formXOffset = -100;
fontSize = 20;
}

Why generated pdf attachment having 0 KB Size?

while generating pdf on localhost using below code is fine,however it generates a pdf of 0KB size while on server . What I am doing wrong here ?
I am using iTextsharp nuget and the code runs fine on local server.
public byte[] GetPDF(string pHTML, List<int> ideaidlist)
{
byte[] bPDF = null;
MemoryStream ms = new MemoryStream();
TextReader txtReader = new StringReader(pHTML);
// Document doc = new Document(PageSize.LETTER, 0, 0, 0, 0);
Document doc = new Document(new Rectangle(864f, 870f), 0, 0, 0, 0);
string Certpath = ConfigurationManager.AppSettings["MailImagePath"]+"Certificates.pdf";//System.Configuration.
string ImgTopPath =ConfigurationManager.AppSettings["CertificateImagePath"];
string ImgMidPath =ConfigurationManager.AppSettings["CertificateImagePath"];
string ImgBotPath =ConfigurationManager.AppSettings["CertificateImagePath"];
FileInfo newExistFile = new FileInfo(Certpath);
if (newExistFile.Exists)
{
newExistFile.Delete();
}
PdfWriter oPdfWriter = PdfWriter.GetInstance(doc,new FileStream(Certpath , FileMode.CreateNew));
HTMLWorker htmlWorker = new HTMLWorker(doc);
doc.Open();
GeneratePdfVM data = new GeneratePdfVM();
foreach (var item in ideaidlist)
{
data = new CommonBL().GetIdeaidListForGenerateCertificates(item);
doc.NewPage();
PdfPTable table = new PdfPTable(1);
table.TotalWidth = 1000;
table.WidthPercentage = 100;
table.LockedWidth = true;
table.HorizontalAlignment = 0;
table.DefaultCell.Border = Rectangle.NO_BORDER;
iTextSharp.text.Image imageTopURL = iTextSharp.text.Image.GetInstance(ImgTopPath + "CertiTop.PNG");
PdfPCell imgTopCell = new PdfPCell(imageTopURL);
imgTopCell.Border = Rectangle.NO_BORDER;
table.AddCell(imgTopCell);
imageTopURL.SpacingAfter = 20;
PdfPCell FirstTxtCell = new PdfPCell();
Paragraph p = new Paragraph(data.EmpName);
p.Font = new Font(Font.FontFamily.HELVETICA, 35f, Font.UNDERLINE);
p.Alignment = Element.ALIGN_CENTER;
FirstTxtCell.AddElement(p);
FirstTxtCell.PaddingRight = 190f;
FirstTxtCell.Border = 0;
table.AddCell(FirstTxtCell);
iTextSharp.text.Image imageMidURL = iTextSharp.text.Image.GetInstance(ImgMidPath + "CertiMid.PNG");
PdfPCell imgMidCell = new PdfPCell(imageMidURL);
imgMidCell.Border = Rectangle.NO_BORDER;
imgMidCell.Border = 0;
imageMidURL.SpacingBefore = 15f;
imageMidURL.Alignment = Element.ALIGN_CENTER;
imgMidCell.PaddingRight = 244f;
table.AddCell(imgMidCell);
PdfPCell SecTextCell = new PdfPCell();
Paragraph para = new Paragraph(data.Title);
para.Font = new Font(Font.FontFamily.HELVETICA, 32f, Font.ITALIC);
para.Alignment = Element.ALIGN_CENTER;
SecTextCell.AddElement(para);
SecTextCell.Border = 0;
SecTextCell.PaddingRight = 200f;
table.AddCell(SecTextCell);
iTextSharp.text.Image imageBotURL = iTextSharp.text.Image.GetInstance(ImgBotPath + "CertiBottom.PNG");
PdfPCell imgBotCell = new PdfPCell(imageBotURL);
imgBotCell.Border = 0;
table.AddCell(imgBotCell);
imageBotURL.SpacingBefore=20;
imageTopURL.ScaleAbsolute(860f, 230f);
imageMidURL.ScaleAbsolute(930f, 100f);
imageBotURL.ScaleAbsolute(864f, 230f);
doc.Open();
doc.Add(table);
htmlWorker.StartDocument();
htmlWorker.Parse(txtReader);
htmlWorker.EndDocument();
}
htmlWorker.Close();
doc.Close();
bPDF = ms.ToArray();
ms.Close();
return bPDF;
}
Here I am calling the above function :
public void GenerateCertificatePDF(List<int> ideaidlist)
{
string HTMLContent = "";
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + "Certificates.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite(GetPDF(HTMLContent, ideaidlist));
}
When you run your code locally, a file is created:
new FileStream(Certpath , FileMode.CreateNew)
That same file is created on the server when you run the code on the server.
However, you also want to send the bytes of the PDF document to the browser. To achieve this by creating a MemoryStream:
MemoryStream ms = new MemoryStream();
When I search your code for the ms variable, I don't find it anywhere except at the very end:
bPDF = ms.ToArray();
ms.Close();
return bPDF;
In other words: you don't write any bytes to ms; the MemoryStream is empty. This is proven by the fact that you get 0 bytes.
Your code works in the sense that a PDF is written on the disk of the server, but that's not what you want, is it? You want this method to create a PDF in memory and then send its bytes to a server.
To achieve this, you need to remove all references to certPath, the part where you exist if the file exists and the FileStream. Instead, you need to write the PDF to the MemoryStream:
PdfWriter oPdfWriter = PdfWriter.GetInstance(doc, ms);
This is explained by Chris Haas in his answer to this question: iTextSharp - Create new document as Byte[]

Special character doesn't appear the same on windows phone emulator and real device

my problem is a bit strange!! I'm going to create a calendar tile with writable bitmap for windows phone 8. so I'm using this character "📆".
I'm using the below code and everything works fine as I expected on emulator. but when I test my app on a real device,calendar character will be appeared different
private void RenderText9()
{
int width = 159;
int height = 159;
string imagename = "SmallBackground";
WriteableBitmap b = new WriteableBitmap(width, height);
var canvas = new Grid();
canvas.Width = b.PixelWidth;
canvas.Height = b.PixelHeight;
var background = new Canvas();
background.Height = b.PixelHeight;
background.Width = b.PixelWidth;
SolidColorBrush backColor = new SolidColorBrush((Color)Application.Current.Resources["PhoneAccentColor"]);
background.Background = backColor;
var textBlock = new TextBlock();
textBlock.Text = "25";
textBlock.TextAlignment = TextAlignment.Center;
textBlock.Margin = new Thickness(0, 72, 0, 0);
textBlock.Width = 159;
textBlock.TextWrapping = TextWrapping.Wrap;
textBlock.Foreground = new SolidColorBrush(Colors.White);
textBlock.FontSize = 35;
var textBlock2 = new TextBlock();
textBlock2.Text = "📆";
textBlock2.TextAlignment = TextAlignment.Center;
textBlock2.Margin = new Thickness(0, 40, 0, 0);
textBlock2.Width = 159;
textBlock2.TextWrapping = TextWrapping.Wrap;
textBlock2.Foreground = new SolidColorBrush(Colors.White); //color of the text on the Tile
textBlock2.FontSize = 75;
canvas.Children.Add(textBlock);
canvas.Children.Add(textBlock2);
b.Render(background, null);
b.Render(canvas, null);
b.Invalidate(); //Draw bitmap
//Save bitmap as jpeg file in Isolated Storage
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream imageStream = new IsolatedStorageFileStream("/Shared/ShellContent/" + imagename + ".jpg", System.IO.FileMode.Create, isf))
{
b.SaveJpeg(imageStream, b.PixelWidth, b.PixelHeight, 0, 100);
}
}
}
this is the tile on both emulator and real device(pay attention to difference).
anybody knows any solution??? I don't understand the reason !!