Replacing an image - c#

I am trying to add or replace an image in an existing PDF file using iTextSharp. The file has 3 layers which are required by the printing company. The content on these layers cannot be merged.
Thus far I have tried many of the code examples (most don't seem to be in C# and can't find the conversion from java). The closest example is:
PdfReader reader = new PdfReader(this.FrontPDFFile);
PdfStamper stamper = new PdfStamper(reader, new FileStream(this.OutputDirectory, FileMode.Create));
var pdfContentBuffer = stamper.GetOverContent(1);
// get image from our api
System.Drawing.Image image = GenerateQRCode("GUOIO", 1000, 1000);
// convert to itextsharp image and insert
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(image, iTextSharp.text.BaseColor.WHITE);
img.SetAbsolutePosition(100, 100);
img.ScaleToFit(100, 100);
pdfContentBuffer.AddImage(img, true);
stamper.Close();
This generates the pdf with the image on, however opening in Illustrator it is not shown, this is likely to be something to do with layers (I am told). Anyone got any ideas?

Related

Inserting an image after text

I'm making a simple program with .NET and iText7
Inserting a signature image in a PDF document is one of the functions under production.
It has been implemented until the image is inserted into the PDF and newly saved, but I don't know if the image goes behind the text.
The Canvas function seems to be possible, but no matter how many times I look at the example, I can't see any parameters related to the placement.
It would be nice to present a keyword that can implement the function.
The sample results are attached to help understanding. In the figure, the left is the capture of the PDF in which I inserted my signature using a word processor, and the right is the capture of the PDF generated through IText.
My iText version is .Net 7.2.1.
I attached the code below just in case it was necessary.
Thank you.
public void PDF_SIGN(FileInfo old_fi)
{
string currentPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
String imageFile = currentPath + "\\sign.jpg";
ImageData data = ImageDataFactory.Create(imageFile);
string source = old_fi.FullName;
string sourceFileName = System.IO.Path.GetFileNameWithoutExtension(source);
string sourceFileExtenstion = System.IO.Path.GetExtension(source);
string dest = old_fi.DirectoryName + "\\" + sourceFileName + "(signed)" + sourceFileExtenstion;
PdfDocument pdfDoc = new PdfDocument(new PdfReader(source), new PdfWriter(dest));
Document document = new Document(pdfDoc);
iText.Layout.Element.Image image = new iText.Layout.Element.Image(data);
image.ScaleAbsolute(Xsize, Ysize);
image.SetFixedPosition(1, Xaxis, Yaxis);
document.Add(image);
document.Close();
pdfDoc.Close();
}
Sample Result (Left: Gaol, Right: Current result):
You can organize content you add using iText in the same pass before or behind each other simply by the order of adding, and layout elements may have background images or colors.
The previously existing content of the source document, consequentially, usually serves as a mere background of everything new. Except, that is, if you draw to a page in a content stream that precedes earlier content.
Unfortunately you cannot use the Document class for this as its renderer automatically works in the foreground. But you can use the Canvas class here; this class only works on a single object (e.g. a single page) but it can be initialized in a far more flexible way.
In your case, therefore, replace
Document document = new Document(pdfDoc);
iText.Layout.Element.Image image = new iText.Layout.Element.Image(data);
image.ScaleAbsolute(Xsize, Ysize);
image.SetFixedPosition(1, Xaxis, Yaxis);
document.Add(image);
document.Close();
by
iText.Layout.Element.Image image = new iText.Layout.Element.Image(data);
image.ScaleAbsolute(Xsize, Ysize);
image.SetFixedPosition(1, Xaxis, Yaxis);
PdfPage pdfPage = pdfDoc.GetFirstPage();
PdfCanvas pdfCanvas = new PdfCanvas(pdfPage.NewContentStreamBefore(), pdfPage.GetResources(), pdfDoc);
using (Canvas canvas = new Canvas(pdfCanvas, pdfPage.GetCropBox()))
{
canvas.Add(image);
}
and you should get the desired result.
(Actually I tested that using Java and ported it to C# in writing this answer. I hope it's ported all right.)
As an aside, if you only want to put an image on the page, you don't really need the Canvas, you can directly use one of the AddImage* methods of PdfCanvas. For multiple elements to be automatically arranged, though, using the Canvas is a good idea.
Also I said above that you cannot use Document here. Actually you can if you replace the document renderer that class uses. For the task at hand that would have been an overkill, though.

How to redact a large rectangle of a PDF by iTextSharp?

I tried to use iTextSharp 5.5.9 to redact PDF files. The problem is when I redact a large rectangle field on a PDF, it can not save the file. This is the code:
PdfReader reader1 = new PdfReader(new FileStream(DesFile, FileMode.Open));
Stream fs = new FileStream(DesFile, FileMode.Open);
PdfStamper stamper = new PdfStamper(reader1, fs);
List<PdfCleanUpLocation> cleanUpLocations = new List<PdfCleanUpLocation>();
cleanUpLocations.Add(new PdfCleanUpLocation(1, new Rectangle(77f,77f,600f,600f), BaseColor.GRAY));
PdfCleanUpProcessor cleaner = new PdfCleanUpProcessor(cleanUpLocations, stamper);
cleaner.CleanUp();
stamper.Close();
reader1.Close();
I use the http://sox.sourceforge.net/sox.pdf to test, if I change the Rectangle to
new Rectangle(77f,77f,200f,200f)
It will work well... But when I change back the larger Rectangle:
new Rectangle(77f,77f,600f,600f)
It stops working. Please help!
iText development usually warns against stamping to the same file the underlying PdfReader reads from. If done as in the OP's code, reading and writing operations can get into each other's way, the results being unpredictable.
After using different files to read from and write to, the OP's solution started working.
If one first reads the source file into memory as a byte[] and then constructs the PdfReader from that array, it is possible to use the same file as output of a PdfStamper operating on that reader. But this pattern is not recommended either: If some problem occurs during stamping, the original file contents may already have been removed, so you have neither the unstamped original PDF nor a stamped result PDF.
It might be embarrassing to have to explain to the client that his documents are completely gone for good...

Unable to fill formfields in a PDF using iTextSharp

I tried to fill my pdf using iTextsharp library.I took reference from this tutorial fill pdf using iTextsharp. But when I tried this example with my pdf file it showed nothing. When I read my pdf file in pdf reader it contains null.
string pdfTemplate = #"c:\authform.pdf";
// create a new PDF reader based on the PDF template document
PdfReader pdfReader = new PdfReader(pdfTemplate);
In this I get null when I read my pdf template.Is there some special format in which the pdf template should be so that it can work with this example.
If you check the tutorial there are two examples.
one is to read fields from existing pdf.
second one is to print data to pdf.
The following is the way to print data to pdf.
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
// set form pdfFormFields
// The first worksheet and W-4 form
pdfFormFields.SetField("f1_01(0)", "1");
pdfStamper.Close();

How to convert PdfContentBytes to Array of Bytes

I'm using iTextSharp DLLin asp.net.
PdfReader reader = new PdfReader(path);
//create footer
MemoryStream outStream = new MemoryStream();
PdfStamper textStamp = new PdfStamper(reader, outStream);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfContentByte pdfPageContents = textStamp.GetOverContent(i);
//How to convert the PdfContentByte to array of bytes here?
}
I want to convert each page of the PDF to JPEG. How to convert the PdfContentByte to array of bytes here?
I don't think your plan is going to work. Not everything that looks like it lives on a "page" actually lives on a page, some things live in a global shared location. So extracting a page's bytes would give you a corrupt document. You could extract every page in a PDF to separate files which would bring over these shared resources but that still is in the PDF format. If you have already written a PDF-to-JPEG routine then maybe you're OK. If you haven't, then iTextSharp won't be able to help you.
iTextSharp doesn't (currently) "know" what a PDF "looks" like, it only knows the contents of the PDF. It "knows" that a run of text exists but it doesn't "know" how that should be rendered visually. It "knows" that a PDF might have two images but doesn't "know" or even care if they overlap, once again that's the renderer's problem.
Once again, if you've written a PDF-to-JPEG routine then disregard all that I'm saying. But the bytes of a PDF have nothing in common with the bytes of JPEG. Although a PDF may contain a JPEG it can also contain many other types of binary data. And that data is probably compressed inside of a stream, too.
Now, if you're looking to just extract images from a PDF, that is something that iTextSharp can help you with.
Try this:
PdfReader reader = new PdfReader(path);
MemoryStream outStream = new MemoryStream();
PdfStamper textStamp = new PdfStamper(reader, outStream);
byte[] content = outStream.ToArray();
You can get a byte[] of a PdfContentByte as follows:
pdfPageContents.getInternalBuffer().toByteArray();

Merging two PDF pages on top of each other

I am looking for a way to merge the content of two pdf pages.
It could be a watermark, an image or whatever.
The scenario is as follows:
I have a Word-addin that allows the user to create different templates for different customers based on several template forms. For each new customer, the user can provide a new letter paper containing header image / logos and footer. This shall be applied anyhow at runtime. Could be an image that is loaded directly into the header of the template (then I would need to render pdf to image, for the letter paper will mostly be provided as pdf-file) or when exporting the document (merging letter paper as background).
But the template shall not be accessible by the user, so this must be done programmatically.
So far, I tried Pdfsharp library, which does not support neither the version of my provided backpapers, nor the version of my documents created in Word 2007.
iTextSharp seemed very promising, but I could not manage to merge the contents so far.
I also tried pdftk.exe, but even when i ran it manually from command line, I got the error: "Done. Input errors, so no output created."
It does not matter how it is handled, but the output matters.
I forgot to mention, there is a whiteline created in the Word-template for archiving purposes, so this part may not be added as image or it has to be added afterwords into the output document.
Thanks in advance!
StampStationery.cs, a sample from the Webified iTextSharp Examples which essentially are the C#/iTextSharp versions of the Java/iText samples from the book iText in Action — 2nd Edition, does show how to add the contents of a page from one PDF document as stationery behind the content of each page of another PDF.
The central method is this:
public byte[] ManipulatePdf(byte[] src, byte[] stationery)
{
// Create readers
PdfReader reader = new PdfReader(src);
PdfReader s_reader = new PdfReader(stationery);
using (MemoryStream ms = new MemoryStream())
{
// Create the stamper
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
// Add the stationery to each page
PdfImportedPage page = stamper.GetImportedPage(s_reader, 1);
int n = reader.NumberOfPages;
PdfContentByte background;
for (int i = 1; i <= n; i++)
{
background = stamper.GetUnderContent(i);
background.AddTemplate(page, 0, 0);
}
}
return ms.ToArray();
}
}
This method returns the manipulated PDF as a byte[].

Categories