I'm using the iTextSharp library version 5.5.6.0. This file contains customizable text fields and it's necessary to keep an interactive text form fields: https://yadi.sk/i/yoUvDI9EmtVhc . But I can't adding an image in PdfTemplate object. The code in c# at this stage is:
string outpath = @"D:\pdf_\output.pdf";
string inpath = @"D:\pdf_\input.pdf";
string stamp = @"D:\pdf_\img.png";
This method does'nt add the image, but the text boxes are active.
public static void onlyInteractive()
{
using (MemoryStream os = new MemoryStream())
using (PdfReader pdfReader = new PdfReader(inpath))
//APPEND mode
using (PdfStamper stamper = new PdfStamper(pdfReader, os, '\0', true))
{
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
image.SetAbsolutePosition(0, 0);
PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
template.AddImage(image);
stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
}
}
The behavior of this method back to the first.
public static void onlyImage()
{
using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
using (PdfReader reader = new PdfReader(inpath))
using (var stamper = new PdfStamper(reader, output, '\0', true))
{
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
image.SetAbsolutePosition(0, 0);
PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
template.AddImage(image);
stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
}
}
The issue with this code is that you grab the output PDF before it is finished:
using (PdfStamper stamper = new PdfStamper(pdfReader, os, '\0', true))
{
[...]
os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
}
When the stamper
is getting closed (here implicitly at the end of its using
block), some not yet stored PDF objects are written and the internal cross references and the file trailer are written.
You write the os
contents to file before that. Thus, your result document is incomplete. Adobe Reader upon opening it repairs it which results in essentially your original document.
This code by itself is correct, it stamps the image onto the document and stores it correctly.
Your problem here is that the document itself is Reader-enabled, i.e. it is signed with a so called usage rights signature. Such signatures tell Adobe Reader upon opening a file to make additional features available displaying editing the document in question.
But when checking the signature on the document with the image, Adobe Reader sees that the document has been changed in a way that is not compatible with the usage rights granted by the signature: An image has been added to the page content which is something not granted by the signature. Thus, Adobe Reader revokes the granted features, in your case form editing.
One option in this situation is to remove that signature. In that case form editing is not granted anymore by means of that signature. But in newer Adobe Reader versions (since version XI if I recall correctly) form editing has been granted to all documents by default! In your case that feature is removed due to the invalidated signature!
This can be done as follows:
using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
using (PdfReader reader = new PdfReader(inpath))
using (var stamper = new PdfStamper(reader, output))
{
reader.RemoveUsageRights();
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
image.SetAbsolutePosition(0, 0);
PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
template.AddImage(image);
stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
}
You can now edit the PDF with image in newer Adobe Readers.
Unfortunately, though, there is an error upon saving the document. I don't know whether they have to do with the fact that the source document is partially invalid (Adobe Preflight complains about a number of issues, foremost the use of an undefined encoding name Win1251Encoding) or whether something else gets broken.
Working in append mode we have to manually remove the usage rights signature. Actually, we'll remove the whole Perms dictionary from the Catalog:
using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
using (PdfReader reader = new PdfReader(inpath))
using (var stamper = new PdfStamper(reader, output, '\0', true))
{
reader.Catalog.Remove(PdfName.PERMS);
stamper.MarkUsed(reader.Catalog);
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
image.SetAbsolutePosition(0, 0);
PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
template.AddImage(image);
stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
}
Now you can edit the form and save the file (at least I can in Adobe Reader DC).
In a comment the OP shared another PDF and stated that it
for the other file is impossible to place a picture on a page with landscape orientation.
There indeed is an issue in the OP's code:
stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
The fixed coordinates 150, 200
are a sign that the OP assumes the lower left page corner to be the origin 0, 0
of the coordinate system. While this often is the case, this is not necessarily true. One always has to take the CropBox (which defaults to the MediaBox) into account, i.e. for the OP's code:
Rectangle cropBox = reader.GetCropBox(1);
stamper.GetOverContent(1).AddTemplate(template, cropBox.Left + 150, cropBox.Bottom + 200, true);
the library takes rotation not correctly, but gives 0 degrees.
But that is correct! Your sample PDF is somewhat special as it uses an unrotated rectangle for landscape and a rotated rectangle for portrait.