Here i am trying to add to images as overlay on text.so i used pushbutton and annotations. but i can write only one image.not able to write second image onwards.Please help me
PdfReader reader1 = new PdfReader(Path);
FileStream fs = new FileStream(OutLocation, FileMode.Create, FileAccess.Write,FileShare.None);
PdfStamper stamper = new PdfStamper(reader1, fs);
PushbuttonField fld = new PushbuttonField(stamper.Writer,
new iTextSharp.text.Rectangle(315, 400, 210, 250), "Test ");
fld.Layout = PushbuttonField.LAYOUT_ICON_ONLY;
string Img = path + "RedSlash.png";
iTextSharp.text.Image jpeg = iTextSharp.text.Image.GetInstance(Img);
jpeg.ScaleToFit(100, 200);
fld.Image = jpeg;
stamper.AddAnnotation(fld.Field, 1);
fld1 = new PushbuttonField(stamper.Writer,
new iTextSharp.text.Rectangle(500, 500, 210, 250), "Test ");
fld1.Layout = PushbuttonField.LAYOUT_ICON_ONLY;
iTextSharp.text.Image jpeg1 = iTextSharp.text.Image.GetInstance(Img);
jpeg1.ScaleToFit(100, 200);
fld1.Image = jpeg1;
stamper.AddAnnotation(fld1.Field, 1);
Answer 1 to your question was: make sure the different fields have different names. You fixed this based on my comment and it worked.
Answer 2 to your question is: don't use form fields to add images, just add the images "the normal way". You asked me for a code sample, I'm giving you a chapter of my book: Working
with existing PDFs. In this chapter, you'll find some examples involving the PdfStamper class. You can find the C# version of these examples here.
Some code:
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
Image img = Image.GetInstance(imagePath);
img.SetAbsolutePosition(0, 0);
int n = reader.NumberOfPages;
PdfContentByte foreground;
for (int i = 1; i <= n; i++) {
foreground = stamper.GetOverContent(i);
foreground.AddImage(img);
}
}
Related
I have this code that will add a watermark on each page:
string watermarkLocation = AppDomain.CurrentDomain.BaseDirectory + "Watermark.png";
Document document = new Document();
PdfReader pdfReader = new PdfReader(fileLocation);
PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(fileLocation.Replace(".pdf", "_marked.pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(watermarkLocation);
img.ScaleToFit(document.PageSize);
img.SetAbsolutePosition(0, 100);
PdfContentByte waterMark;
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
waterMark = stamp.GetOverContent(page);
waterMark.AddImage(img);
}
stamp.FormFlattening = true;
stamp.Close();
return fileLocation.Replace(".pdf", "_marked.pdf");
But on PDFs that have textboxes, the image will go behind the textbox/form. I thought flattening the file will fix this, but it does not work.
I used a full image as a test but the watermark in the end will have transparency.
Here's the final code I'm using. As my comment mentioned, there's basically 2 readers/stamps, one to flatten the file and another to add the watermark.
Flatten file:
private byte[] FlattenPdfFormToBytes(PdfReader reader)
{
var memStream = new MemoryStream();
var stamper = new PdfStamper(reader, memStream) { FormFlattening = true };
stamper.Close();
return memStream.ToArray();
}
Add Watermark (which will call FlattenPdfFormToBytes):
public string AddWatermark(string fileLocation)
{
string watermarkLocation = AppDomain.CurrentDomain.BaseDirectory + "Watermark.png";
Document document = new Document();
PdfReader pdfReader = new PdfReader(fileLocation);
PdfReader pdfFlatten = new PdfReader(FlattenPdfFormToBytes(pdfReader)); // The secret sauce is this!!!
PdfStamper stamp = new PdfStamper(pdfFlatten, new FileStream(fileLocation.Replace(".pdf", "_marked.pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(watermarkLocation);
img.ScaleToFit(document.PageSize);
img.SetAbsolutePosition(0, 100);
PdfContentByte waterMark;
for (int page = 1; page <= pdfFlatten.NumberOfPages; page++)
{
waterMark = stamp.GetOverContent(page);
waterMark.AddImage(img);
}
stamp.Close();
return fileLocation.Replace(".pdf", "_marked.pdf");
}
This was my code for itextsharp which worked ok. It displayed "Quote Only" in the middle of each page in a pdf file.
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(Server.MapPath(#"~\Content\WaterMarkQuoteOnly.png"));
PdfReader readerOriginalDoc = new PdfReader(File(all, "application/pdf").FileContents);
int n = readerOriginalDoc.NumberOfPages;
img.SetAbsolutePosition(0, 300);
PdfGState _state = new PdfGState()
{
FillOpacity = 0.1F,
StrokeOpacity = 0.1F
};
using (MemoryStream ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(readerOriginalDoc, ms, '\0', true))
{
for (int i = 1; i <= n; i++)
{
PdfContentByte content = stamper.GetOverContent(i);
content.SaveState();
content.SetGState(_state);
content.AddImage(img);
content.RestoreState();
}
}
//return ms.ToArray();
all = ms.GetBuffer();
}
This is my new itext 7 code, this also displays the watermark but the position is wrong. I was dismayed to see that you cant add an image to the canvas but you have to add ImageData when the position is being set on the image. The image is also way smaller and back to front.
var imagePath = Server.MapPath(#"~\Content\WaterMarkQuoteOnly.png");
var tranState = new iText.Kernel.Pdf.Extgstate.PdfExtGState();
tranState.SetFillOpacity(0.1f);
tranState.SetStrokeOpacity(0.1f);
ImageData myImageData = ImageDataFactory.Create(imagePath, false);
Image img = new Image(myImageData);
img.SetFixedPosition(0, 300);
var reader = new PdfReader(new MemoryStream(all));
var doc = new PdfDocument(reader);
int pages = doc.GetNumberOfPages();
using (var ms = new MemoryStream())
{
var writer = new PdfWriter(ms);
var newdoc = new PdfDocument(writer);
for (int i = 1; i <= pages; i++)
{
//get existing page
PdfPage page = doc.GetPage(i);
//copy page to new document
newdoc.AddPage(page.CopyTo(newdoc)); ;
//get our new page
PdfPage newpage = newdoc.GetPage(i);
Rectangle pageSize = newpage.GetPageSize();
//get canvas based on new page
var canvas = new PdfCanvas(newpage);
//write image data to new page
canvas.SaveState().SetExtGState(tranState);
canvas.AddImage(myImageData, pageSize, true);
canvas.RestoreState();
}
newdoc.Close();
all = ms.GetBuffer();
ms.Flush();
}
You are doing something strange with the PdfDocument objects, and you are also using the wrong AddImage() method.
I am not a C# developer, so I rewrote your example in Java. I took this PDF file:
And I took this image:
Then I added the image to the PDF file using transparency with the following result:
The code to do this, was really simple:
public void createPdf(String src, String dest) throws IOException {
PdfExtGState tranState = new PdfExtGState();
tranState.setFillOpacity(0.1f);
ImageData img = ImageDataFactory.create(IMG);
PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(reader, writer);
for (int i = 1; i <= pdf.getNumberOfPages(); i++) {
PdfPage page = pdf.getPage(i);
PdfCanvas canvas = new PdfCanvas(page);
canvas.saveState().setExtGState(tranState);
canvas.addImage(img, 36, 600, false);
canvas.restoreState();
}
pdf.close();
}
For some reason, you created two PdfDocument instances. This isn't necessary. You also used the AddImage() method passing a Rectangle which resizes the image. Also make sure that you don't add the image as an inline image, because that bloats the file size.
I don't know which programming language you are using. For instance: I am not used to variables that are created using var such as var tranState. It should be very easy for you to adapt my Java code though. It's just a matter of changing lowercases into uppercases.
I have a PDF of a blank 1-page MS Word doc. I want to add a text box to it. Code as follows:
void addAnnotation()
{
string filename = #"C:\Users\userID\Documents\Visual Studio 2013\Projects\PDFConverterTester\TestAddSrc.pdf";
string destFile = #"C:\Users\userID\Documents\Visual Studio 2013\Projects\PDFConverterTester\TestAddDest.pdf";
PdfReader pdfReader = new PdfReader(filename);
FileStream stream = new FileStream(destFile, FileMode.Create);
PdfStamper pdfStamper = new PdfStamper(pdfReader, stream);
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(100,100, 100, 100);
PdfWriter pdfWriter = pdfStamper.Writer;
PdfAnnotation annot = PdfAnnotation.CreateStamp(pdfWriter, rect, "XYZABC add rect", "new rectangle");
pdfStamper.AddAnnotation(annot, 1);
pdfStamper.Close();
}
When I open TestAddDest.pdf, it's blank, just like the source PDF, and the file size is the same, so I'm assuming the annotation has not been added. How can I add this text box?
Edit:
Source PDF: http://docdro.id/jAOpxr3
Destination PDF: http://docdro.id/gOaHsQm
The reason the PDF is blank is because the Rectangle is zero width and zero height :
iTextSharp.text.Rectangle rect = new
iTextSharp.text.Rectangle(100,100, 100, 100);
Put a breakpoint on that line or:
Console.WriteLine("W: {0}, H: {1}", rect.Width, rect.Height);
output:
W: 0, H: 0
Try something like this, which places the Rectangle at the top of the page:
Rectangle rect = new Rectangle(20, 700, 400, 776);
Destination PDF:
i have a pdf file. There is a footer on each page. now i want to replace a static text exist on footer with some other text. Please Help me.....
I have tried with following case but not success
PdfReader readere = new PdfReader(#"D:\MergedOutput.pdf");
for (int i = 1; i < readere.NumberOfPages; i++)
{
byte[] contentBytes = PdfEncodings.ConvertToBytes(PdfTextExtractor.GetTextFromPage(readere, i), PdfObject.TEXT_PDFDOCENCODING);
byte[] searchStringArray = PdfEncodings.ConvertToBytes("Side", PdfObject.TEXT_PDFDOCENCODING);
byte[] replacedByString = PdfEncodings.ConvertToBytes("Hello", PdfObject.TEXT_PDFDOCENCODING);
string searchString = PdfEncodings.ConvertToString(searchStringArray, PdfObject.TEXT_PDFDOCENCODING);
string contentString = PdfEncodings.ConvertToString(contentBytes, PdfObject.TEXT_PDFDOCENCODING);
string replaceString = PdfEncodings.ConvertToString(replacedByString, PdfObject.TEXT_PDFDOCENCODING);
if (contentString.Contains(searchString))
{
contentString = contentString.Replace(searchString, replaceString);
}
readere.SetPageContent(i, PdfEncodings.ConvertToBytes(contentString, PdfObject.TEXT_PDFDOCENCODING));
}
Suppose you have a byte array of PDF data or any PDF files. First convert this file to byte array.. after that we have to apply below code section. its working fine for me...
iTextSharp.text.Font blackFont = FontFactory.GetFont("Seoge UI", 10, iTextSharp.text.Font.NORMAL, new BaseColor(Color.FromArgb(97, 102, 116)));
//Path to where you want the file to output
string outputFilePath = "MergedOutputt.pdf";
//Path to where the pdf you want to modify is
//string inputFilePath = "D:\\MergedOutput.pdf";
try
{
using (Stream outputPdfStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
using (Stream outputPdfStream2 = new FileStream(outputFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
{
//Opens the unmodified PDF for reading
var reader = new PdfReader(MergedOutputStream.ToArray());
//Creates a stamper to put an image on the original pdf
var stamper = new PdfStamper(reader, outputPdfStream) { FormFlattening = true, FreeTextFlattening = true };
for (int i = 1; i <= reader.NumberOfPages; i++)
{
//Creates an image that is the size i need to hide the text i'm interested in removing
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(new Bitmap(120, 20), BaseColor.WHITE);
//Sets the position that the image needs to be placed (ie the location of the text to be removed)
image.SetAbsolutePosition(reader.GetPageSize(i).Width - 120, 42);
//Adds the image to the output pdf
stamper.GetOverContent(i).AddImage(image, true);
//Creates the first copy of the outputted pdf
PdfPTable table = new PdfPTable(1);
float[] width = new float[] { 38 };
table.SetTotalWidth(width);
PdfContentByte pb;
//Get PdfContentByte object for first page of pdf file
pb = stamper.GetOverContent(i);
cellSequenceNumber = new PdfPCell(new Phrase(new Chunk("Side " + i.ToString(), blackFont)));
cellSequenceNumber.Border = 0;
table.AddCell(cellSequenceNumber);
table.WriteSelectedRows(0, table.Rows.Count, reader.GetPageSize(i).Width - 82, 54, pb);
}
stamper.Close();
//Opens our outputted file for reading
var reader2 = new PdfReader(outputPdfStream2);
reader2.Close();
}
}
It will generate a pdf file named as "MergedOutputt.pdf"
The title sums it all.
I want to add a text to an existing PDF file using iTextSharp, however i can't find how to do it anywhere in the web...
PS: I cannot use PDF forms.
I found a way to do it (dont know if it is the best but it works)
string oldFile = "oldFile.pdf";
string newFile = "newFile.pdf";
// open the reader
PdfReader reader = new PdfReader(oldFile);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
// open the writer
FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
// select the font properties
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252,BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.DARK_GRAY);
cb.SetFontAndSize(bf, 8);
// write the text in the pdf content
cb.BeginText();
string text = "Some random blablablabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(1, text, 520, 640, 0);
cb.EndText();
cb.BeginText();
text = "Other random blabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(2, text, 100, 200, 0);
cb.EndText();
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
// close the streams and voilá the file should be changed :)
document.Close();
fs.Close();
writer.Close();
reader.Close();
I hope this can be usefull for someone =) (and post here any errors)
In addition to the excellent answers above, the following shows how to add text to each page of a multi-page document:
using (var reader = new PdfReader(#"C:\Input.pdf"))
{
using (var fileStream = new FileStream(#"C:\Output.pdf", FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
for (var i = 1; i <= reader.NumberOfPages; i++)
{
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 12);
var multiLineString = "Hello,\r\nWorld!".Split('\n');
foreach (var line in multiLineString)
{
contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, line, 200, 200, 0);
}
contentByte.EndText();
contentByte.AddTemplate(importedPage, 0, 0);
}
document.Close();
writer.Close();
}
}
This worked for me and includes using OutputStream:
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(Request.MapPath("Template.pdf")), null);
Rectangle size = reader.GetPageSizeWithRotation(1);
using (Stream outStream = Response.OutputStream)
{
Document document = new Document(size);
PdfWriter writer = PdfWriter.GetInstance(document, outStream);
document.Open();
try
{
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
try
{
cb.SetFontAndSize(BaseFont.CreateFont(), 12);
cb.SetTextMatrix(110, 110);
cb.ShowText("aaa");
}
finally
{
cb.EndText();
}
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
}
finally
{
document.Close();
writer.Close();
reader.Close();
}
}
Here is a method that uses stamper and absolute coordinates showed in the different PDF clients (Adobe, FoxIt and etc. )
public static void AddTextToPdf(string inputPdfPath, string outputPdfPath, string textToAdd, System.Drawing.Point point)
{
//variables
string pathin = inputPdfPath;
string pathout = outputPdfPath;
//create PdfReader object to read from the existing document
using (PdfReader reader = new PdfReader(pathin))
//create PdfStamper object to write to get the pages from reader
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(pathout, FileMode.Create)))
{
//select two pages from the original document
reader.SelectPages("1-2");
//gettins the page size in order to substract from the iTextSharp coordinates
var pageSize = reader.GetPageSize(1);
// PdfContentByte from stamper to add content to the pages over the original content
PdfContentByte pbover = stamper.GetOverContent(1);
//add content to the page using ColumnText
Font font = new Font();
font.Size = 45;
//setting up the X and Y coordinates of the document
int x = point.X;
int y = point.Y;
y = (int) (pageSize.Height - y);
ColumnText.ShowTextAligned(pbover, Element.ALIGN_CENTER, new Phrase(textToAdd, font), x, y, 0);
}
}
Here is a method To print over images:
taken from here.
Use a different layer for your text you're putting over the images, and also make sure to use the GetOverContent() method.
string oldFile = "FileWithImages.pdf";
string watermarkedFile = "Layers.pdf";
// Creating watermark on a separate layer
// Creating iTextSharp.text.pdf.PdfReader object to read the Existing PDF Document
PdfReader reader1 = new PdfReader(oldFile);
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
// Getting total number of pages of the Existing Document
int pageCount = reader1.NumberOfPages;
// Create New Layer for Watermark
PdfLayer layer = new PdfLayer("Layer", stamper.Writer);
// Loop through each Page
for (int i = 1; i <= pageCount; i++)
{
// Getting the Page Size
Rectangle rect = reader1.GetPageSize(i);
// Get the ContentByte object
PdfContentByte cb = stamper.GetOverContent(i);
// Tell the cb that the next commands should be "bound" to this new layer
cb.BeginLayer(layer);
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.RED);
cb.SetFontAndSize(bf, 100);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Some random blablablabla...", rect.Width / 2, rect.Height / 2, - 90);
cb.EndText();
// Close the layer
cb.EndLayer();
}
}