I am able to overlay an image onto an existing PDF document using the PDFStamper and the PdfContentByte content.AddImage method.
My problem comes up when the existing document already has an image overlayed on top. You can actually see the top edge of the small image I am trying to overlay. It is clearly hidden beneath the existing image overlay.
I am having issues trying to get my overlayed image to show up on top of the existing image overlay.
My code:
System.Drawing.Image bitmap
PdfReader pdfReader = new PdfReader(pathToOriginalPdf);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(pathToTimestampedPdf, FileMode.Create, FileAccess.Write, FileShare.None));
MemoryStream imageStream = new MemoryStream();
bitmap.Save(imageStream, ImageFormat.Bmp);
byte[] bitmapBytes = imageStream.ToArray();
iTextSharp.text.Image image = Image.GetInstance(bitmapBytes);
PdfContentByte underContent;
try
{
underContent = pdfStamper.GetOverContent(1);
underContent.AddImage(image);
}
I need a way to either flatten the existing image overlay onto the PDF content or set the z-order such that my newly added overlay can sit on top.
For some reason the PdfStamper is choosing to place the new image below the existing one.
Thanks in advance.
It would help if we could see the PDF in question. Then we wouldn't have to guess, we would know.
None the less, I suspect your "existing image overlay" is part of an annotation. Nothing you put into page contents will ever appear above an annotation.
Options (if I'm right):
Add your own annotation
For this, I'd use a PushbuttonField with LAYOUT_ICON_ONLY. Draw your image into a PdfTemplate, and use that for the button's "icon".
Z-order for annotations is determined by the order of the page's annotation array. New annotations are appended to this array. No problem.
PushbuttonField fld = new PushbuttonField(stamper.getWriter(), box, name);
fld.setLayout(PushbuttonField.LAYOUT_ICON_ONLY);
fld.setImage(myImage);
stamper.addAnnotation(fld.getField(), 1);
You might need to mess around with setScaleIcon(), setHorizontalAdjustment(), setVerticalAdjustment(), setProportionalIcon(), and maybe a couple others to get your image to look exactly how you want it.
Flatten in one pass, add your image in another
If the existing image annotation is something iText can flatten (maybe, maybe not), you can do what you want in two passes. The first pass would simply "setFormFlattening(true);close();", while the second would be everything you're doing now.
ByteArrayOutputStream output = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper( firstReader, output );
stamper.setFormFlattening(true);
stamper.setFreeTextFlatten(true); // probably not needed.
stamper.close();
PdfReader secondReader = new PdfReader(output.toByteArray());
FileOutputStream finalOutput = new FileOutputStream( outputPath );
stamper = new PdfStamper(secondReader, finalOutput);
// do your thing here.
stamper.getOverContent(1).addImage(image);
Related
Hello We are trying to create a custom template system based such as WPF Header and Footer elements, with a canvas for 2D Drawings for export to PDF. The problem is the XpsWriter takes about 7 seconds to write the XPS Document, and another 3 Seconds to convert to pdf with PDFSharp. We need to get this down as the user waits for the PDF. I first suspected its due to the number of FrameworkElements in the, but there are only 5000. The framework elements are mostly PATH data with fills, strokes, and brushes.
Canvas ComplexCanvas = new Canvas();
ComplexCanvas.Children.Add(5000Elements);
System.Windows.Documents.FixedDocument fixedDoc = new System.Windows.Documents.FixedDocument();
System.Windows.Documents.PageContent pageContent = new System.Windows.Documents.PageContent();
System.Windows.Documents.FixedPage fixedPage = new System.Windows.Documents.FixedPage();
//Create first page of document
fixedPage.Children.Add(ComplexCanvas);
fixedPage.Width = PageWidth;
fixedPage.Height = PageHeight;
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
System.Windows.Xps.Packaging.XpsDocument xpsd = new XpsDocument(Path, System.IO.FileAccess.Write);
System.Windows.Xps.XpsDocumentWriter xw = XpsDocument.CreateXpsDocumentWriter(xpsd);
xw.Write(fixedDoc);
xpsd.Close();
Does anyone know a way to speed this up? Perhaps some type Visual Object, or "Flatten" the Canvas somehow or any ideas. When it does work the PDF is over 5MB.
Would like to keep it VECTOR as much as possible
There are several ways to speed up the conversion from WPF to XPS to PDF:-
Freeze any pens or brushes as this will speed up rendering:-
SolidColorBrush brush = new SolidColorBrush(Colors.PaleGreen);
brush.Opacity = .25d;
brush.Freeze();
Pen paleGreenPen = new Pen(brush, 1);
paleGreenPen.Freeze();
Pen linePen = new Pen(Brushes.Red, 1);
linePen.Freeze();
Render in the background (create a background UI thread).
Do not save the interim XPS document to disk but use a MemoryStream.
I'm trying to fill a PDF form using iTextSharp, but being cursed with the need for Scandinavian characters (åäöøæ etc) I can't use the built in Helvetica. The closest thing would be to use Arial, BUT if I embed Arial I'm stuck with a PDF template 6 times larger than the original file.
So, my question, is there a way to use Helvetica when creating the template (in order to keep the size down) and then override this in the code when filling the PDF?
As it stands right now I have this:
PdfStamper pdfStamper = new PdfStamper(new PdfReader(templateFile), new FileStream(fileName, FileMode.Create));
AcroFields acroFields = pdfStamper.AcroFields;
acroFields.SetField("txtDocumentId", dnData.DocumentId);
acroFields.SetField("txtName", dnData.Name);
pdfStamper.FormFlattening = true;
pdfStamper.Close();
I would prefer to define an unembedded font (Arial) for the fields since all end users will have Arial installed on their Machines.
Is this doable?
Using the below code pdf stamping is working fine but if the pdf page does not have header info or body is empty then stamping is not working I mean pdfData.ShowText(strCustomMessage) is not working.
//create pdfreader object to read sorce pdf
PdfReader pdfReader=new PdfReader(Server.MapPath("Input") + "/" + "input.pdf");
//create stream of filestream or memorystream etc. to create output file
FileStream stream = new FileStream(Server.MapPath("Output") + "/output.pdf", FileMode.OpenOrCreate);
//create pdfstamper object which is used to add addtional content to source pdf file
PdfStamper pdfStamper = new PdfStamper(pdfReader,stream);
//iterate through all pages in source pdf
for (int pageIndex = 1; pageIndex <= pdfReader.NumberOfPages; pageIndex++)
{
//Rectangle class in iText represent geomatric representation... in this case, rectanle object would contain page geomatry
Rectangle pageRectangle = pdfReader.GetPageSizeWithRotation(pageIndex);
//pdfcontentbyte object contains graphics and text content of page returned by pdfstamper
PdfContentByte pdfData = pdfStamper.GetUnderContent(pageIndex);
//create fontsize for watermark
pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 40);
//create new graphics state and assign opacity
PdfGState graphicsState = new PdfGState();
graphicsState.FillOpacity = 0.4F;
//set graphics state to pdfcontentbyte
pdfData.SetGState(graphicsState);
//set color of watermark
pdfData.SetColorFill(BaseColor.BLUE);
//indicates start of writing of text
pdfData.BeginText();
//show text as per position and rotation
pdfData.SetTextMatrix(pageRectangle.Width/2,pageRectangle.Height/2); pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 9);
string strCustomMessage="PDF Stamping Test"
pdfData.ShowText(strCustomMessage);
//call endText to invalid font set
pdfData.EndText();
}
//close stamper and output filestream
pdfStamper.Close();
stream.Close();
I think your question is wrong. Would do you mean when you say "the pdf page does not have header info or body is empty"? Because that doesn't make sense.
A few observations: I think you're using an obsolete version of iTextSharp. Read the FAQ to find out why this is a bad idea.
Newer versions of iTextSharp will throw an exception because of this error:
pdfData.BeginText();
//show text as per position and rotation
string strCustomMessage="PDF Stamping Test"
pdfData.ShowText(strCustomMessage);
//call endText to invalid font set
pdfData.EndText();
In these lines, you are violating the PDF reference: you are showing text within a BT/ET sequence without defining a font and size. Had you used a newer version of iTextSharp, an exception would have pointed that out. You need to move the line with the SetFontAndSize() method inside the BeginText()/EndText() sequence. It's illegal to use it outside a text object.
Also: why are you using BeginText()/EndText() to add text? That is code for PDF specialists. Read the documentation to find out how to use ColumnText.ShowTextAligned(). The ShowTextAligned() method is a convenience method written for developer who aren't fluent in PDF syntax.
Whether or not the text added with ShowText() is visible will depend on:
the opacity of the page: Suppose that your page consists of a scanned image, you won't see any text, because you're adding the text under the image. Use the GetOverContent() method instead of the GetUnderContent() method to avoid this.
the position on the page: I see that you get the size of the page using the GetPageSizeWithRotation() method, but I don't see you doing anything with that info. I don't see at which coordinate you are showing the text. That is also wrong. You need to make sure that you add the text inside the visible area of the page.
This answer lists several problems with your code. It would be better if you simplify your code by using the ShowTextAligned() and correct X,Y coordinates.
I have 2 asp.net chart control which i want to convert to pdf. I am using iTextSharp to convert the images to pdf.
The issue is with the position of images, i want images to come next to other.
i tried to setpagesize but it didnt worked.
Document pdfDoc = new Document(PageSize.A4);
PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.SetPageSize(iTextSharp.text.PageSize.A4.Rotate());
Chart1.SaveImage(stream, ChartImageFormat.Png);
iTextSharp.text.Image chartImage = iTextSharp.text.Image.GetInstance(stream.GetBuffer());
chartImage.ScalePercent(75f);
pdfDoc.Add(chartImage);
Chart2.SaveImage(stream, ChartImageFormat.Png);
iTextSharp.text.Image chartImage1 = iTextSharp.text.Image.GetInstance(stream.GetBuffer());
chartImage1.ScalePercent(75f);
pdfDoc.Add(chartImage1);
The best way to position images next to each other, is to add them to a ´PdfPTable´. I've created a small example in Java: ImagesNextToEachOther
As you can see, we wrap images inside a cell, asking the cell to scale the image so that it fits the width of the cell.
You'll have to make small changes to the code, as I've used iText instead of iTextSharp, but the difference should be minimal.
alt text http://img517.imageshack.us/img517/8124/56267347.jpg
Assuming i have a winform that has a button called "Create a Quote". Once user clicks it,
a PDF File gets created on desktop. The PDF File has a fixed design/structure e.g. the logo is at the top left corner, the headers are fixed, etc. However, the data it self is pulled from a database.
As you see above, Quotation #, Description, Qty, U.P (USD), T.P (USD) records should be fetched from the db and dumped in the pdf template then create the pdf for user.
I haven't done this before. I hope my question is clear enough. Feel free to put useful web links that help me achieve it.
Any help will be appreciated.
You should look at two of the most popular open-source PDF libraries for C#, namely:
ITextSharp and PDFSharp
Both allow you to programatically create PDF files. Here's a quick 'hello word' example with PDFSharp:
// Create a new PDF document
PdfDocument document = new PdfDocument();
document.Info.Title = "Created with PDFsharp";
// Create an empty page
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
// Create a font
XFont font = new XFont("Verdana", 20, XFontStyle.BoldItalic);
// Draw the text
gfx.DrawString("Hello, World!", font, XBrushes.Black,
new XRect(0, 0, page.Width, page.Height),
XStringFormats.Center);
// Save the document...
const string filename = "HelloWorld.pdf";
document.Save(filename);
// ...and start a viewer.
Process.Start(filename);