I have 5 pages pdf need to highlight specific element based on coordinates
Have X top left,Y top left,X top right ,Y top right , X bottom right , Y bottom right ,X bottom left, Y bottom left .
I tried below code using iTextsharp please suggest how can we do this including page no
using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
//Create a simple test file
string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf");
//Create a new file from our test file with highlighting
string highLightFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Highlighted.pdf");
//Bind a reader and stamper to our test PDF
PdfReader reader = new PdfReader(outputFile);
using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
//Create a rectangle for the highlight. NOTE: Technically this isn't used but it helps with the quadpoint calculation
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(60.6755f, 749.172f, 94.0195f, 735.3f);
//Create an array of quad points based on that rectangle. NOTE: The order below doesn't appear to match the actual spec but is what Acrobat produces
float[] quad = { rect.Left, rect.Bottom, rect.Right, rect.Bottom, rect.Left, rect.Top, rect.Right, rect.Top };
//Create our hightlight
PdfAnnotation highlight = PdfAnnotation.CreateMarkup(stamper.Writer, rect, null, PdfAnnotation.MARKUP_HIGHLIGHT, quad);
//Set the color
highlight.Color = BaseColor.YELLOW;
//Add the annotation
stamper.AddAnnotation(highlight,1);
}
}
Output
Highlight element in rectangular.
Need to highlight 3rd page of PDF.
"boundingBox": [3.2924,7.7146,5.7564,7.7038,5.7671,7.9836,3.3032,7.9943]
this "text": "66 66 6666 6666" should get higlighted
Input File
Output File
Wrong page
First of all, you add the annotation to the wrong page.
You say
Need to highlight 3rd page of PDF.
but you put it on page 1:
stamper.AddAnnotation(highlight,1);
To fix this, change the page number there:
stamper.AddAnnotation(highlight,3);
Wrong coordinates
Neither the coordinates in your code
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(60.6755f, 749.172f, 94.0195f, 735.3f);
nor those you gave in that JSON'ish way
"boundingBox": [3.2924,7.7146,5.7564,7.7038,5.7671,7.9836,3.3032,7.9943]
are anywhere near the location you want to highlight, at least not in the regular PDF coordinate system given by the page media box. By measuring in Adobe Acrobat I got the following approximate coordinates:
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(240f, 264f, 413f, 289f);
If any of the coordinates you showed are meant to be actual coordinates of the image part to highlight, ask the provider of those coordinates about the coordinate system used and accordingly transform to coordinates in the given page's media box.
Questionable order in QuadPoints
You create quad using this order:
float[] quad = { rect.Left, rect.Bottom, rect.Right, rect.Bottom, rect.Left, rect.Top, rect.Right, rect.Top };
This results in concave caps. You probably want to use
float[] quad = { rect.Left, rect.Top, rect.Right, rect.Top, rect.Left, rect.Bottom, rect.Right, rect.Bottom };
instead which Adobe Reader shows as convex caps. For a background read this answer.
Example output
You say:
"66 66 6666 6666" should get higlighted
With the three changes above applied to your code I get this:
Related
I have a very simple code that places the png image into PDF
Document pdfDoc = new Document(PageSize.A4, 25, 25, 25, 10);
string pathfile = ConfigurationManager.AppSettings["Temp_SaveLocation"];
string fileName = "SomeName.pdf";
path = pathfile + fileName;
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream(path, FileMode.Create));
pdfDoc.Open();
Image imghead = Image.GetInstance(templateFolder + "Letterhead.png");
imghead.SetAbsolutePosition(0, 0);
pdfDoc.Add(imghead);
pdfWriter.CloseStream = true;
pdfDoc.Close();
However, no matter what position for the image I set, that image ends up on a very bottom of a document. I even tried negative values for the absolute position. Nevertheless, the image stays on the very bottom of a document. How can I bring an image to a very top?
Thank you very much in advance
I found out that image will be to the top when this code is removed.
imghead.SetAbsolutePosition(0, 0);
I agree with K J. By setting imghead.SetAbsolutePosition(0, 0), you are setting your image to be at (X,Y) co-ordinate which is mostly lower left co-ordinate of the page.
Generally, lower-left corner of the page coincides with the origin of the coordinate system (0, 0). The upper-right corner of the page coincides with the coordinate (595, 842). You either remove or comment this method imghead.SetAbsolutePosition(0, 0) or adjust the Y co-ordinate of it to move the image towards the upper side of the page.
I have some code used to watermark PDFs using iTextSharp. The code works fine for most PDFs, but there has been one test case where the watermark is not visible on a PDF of a scanned document. (I have other scanned documents where it does appear though).
I am using the GetOverContent() method.
This is my code for adding the watermark;
using (PdfReader reader = new PdfReader(this.inputFilename))
{
// Set transparent - 1
PdfGState gstate = new PdfGState();
gstate.FillOpacity = 0.4f;
gstate.StrokeOpacity = 0.5f;
// 2
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
using (var stream = new MemoryStream())
{
var pdfStamper = new PdfStamper(reader, stream);
// Must start at 1 because 0 is not an actual page.
for (int i = 1; i <= reader.NumberOfPages; i++)
{
Rectangle pageSize = reader.GetPageSizeWithRotation(i);
// Gets the content ABOVE the PDF, Another option is GetUnderContent(...)
// which will place the text below the PDF content.
PdfContentByte pdfPageContents = pdfStamper.GetOverContent(i);
pdfPageContents.BeginText(); // Start working with text.
// 1
pdfPageContents.SaveState();
pdfPageContents.SetGState(gstate);
float hypotenuse = (float)Math.Sqrt(Math.Pow(pageSize.Width, 2) + Math.Pow(pageSize.Height, 2));
float glyphWidth = baseFont.GetWidth("My watermark text");
float fontSize = 1000 * (hypotenuse * 0.8f) / glyphWidth;
float angle = (float)(Math.Atan(pageSize.Height / pageSize.Width) * (180 / Math.PI));
// Create a font to work with
pdfPageContents.SetFontAndSize(baseFont, fontSize);
pdfPageContents.SetRGBColorFill(128, 128, 128); // Sets the color of the font, GRAY in this instance
// Note: The x,y of the Pdf Matrix is from bottom left corner.
// This command tells iTextSharp to write the text at a certain location with a certain angle.
// Again, this will angle the text from bottom left corner to top right corner and it will
// place the text in the middle of the page.
pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "My watermark text", pageSize.Width / 2, pageSize.Height / 2, angle);
pdfPageContents.EndText(); // Done working with text
pdfPageContents.RestoreState();
}
pdfStamper.FormFlattening = true; // enable this if you want the PDF flattened.
pdfStamper.FreeTextFlattening = true; // enable this if you want the PDF flattened.
pdfStamper.Close(); // Always close the stamper or you'll have a 0 byte stream.
return stream.ToArray();
}
}
Does anyone have any ideas as to why the watermark may not be appearing and what I can try to fix it?
Kind regards.
The code is based on an assumption it even documents as a fact:
// Note: The x,y of the Pdf Matrix is from bottom left corner.
// This command tells iTextSharp to write the text at a certain location with a certain angle.
// Again, this will angle the text from bottom left corner to top right corner and it will
// place the text in the middle of the page.
pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "My watermark text", pageSize.Width / 2, pageSize.Height / 2, angle);
The assumption that the x,y of the Pdf Matrix is from bottom left corner unfortunately is wrong: While it indeed is very often the case that the origin of the PDF coordinate system (the default user space coordinate system, to be more precise) is in the lower left corner of the page, this is not required, the origin actually can be literally anywhere (within reasonable limits).
Thus, one has to take the lower left coordinates of the Rectangle pageSize into consideration, too.
The OP meanwhile has confirmed:
I had assumed that the bottom left of the page would have co-ordinates of (0,0) but for this document the co-ordinates were (0, 7022).
I am trying to get the x and y coordinates from a pdf document on click event. Pdf documents do not have DOM that's why I am overlaying a div on the top of the pdf document to get the coordinates from the div. I am using itextsharp library and trying to stamp a value you the pdf document. Unfortunately the x and y coordinates of the div are in pixels and I need to relate them to the values in the stamper.
The X coordinates that I am getting from the div click event are: 80, 300, 600, 880
and the X coordinates that I need to enter in the stamper are 10, 205,405,600. What ratio do I need to apply to convert the div coordinates to the stamper coordinates.
private static void InsertTextToPdf(string sourceFileName, string newFileName)
{
using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
{
using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
{
PdfReader pdfReader = new PdfReader(pdfStream);
iTextSharp.text.Rectangle pageSize = pdfReader.GetPageSize(1);
Console.Write(pageSize);
PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
pdfContentByte.SetColorFill(BaseColor.RED);
pdfContentByte.SetFontAndSize(baseFont, 12);
pdfContentByte.BeginText();
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Test", 10, 190, 0);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Test", 205, 190, 0);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Test", 405, 190, 0);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Test", 600, 190, 0);
pdfContentByte.EndText();
pdfStamper.Close();
}
}
}
Trying to get the userUnit - in my case they are null
PdfReader pdfReader = new PdfReader(pdfStream);
iTextSharp.text.Rectangle pageSize = pdfReader.GetPageSize(1);
Console.Write(pageSize);
iTextSharp.text.pdf.PdfDictionary pageDict = pdfReader.GetPageN(1);
iTextSharp.text.pdf.PdfNumber userUnit = pageDict.GetAsNumber(iTextSharp.text.pdf.PdfName.USERUNIT);
Console.Write("\nPageDict " + pageDict);
Console.Write("\nUser Unit " + userUnit);
You are making different assumptions that are wrong.
There is an FAQ on the official iText web site, where you can find questions that were answered before on Stack Overflow.
Measurement unit
The first FAQ entry you have to read is: How to get the UserUnit from a PDF file?
I quote:
FAQ What is the measurement unit in PDF documents? Most of the measurements
in PDFs are expressed in user space units. ISO-32000-1 (section 8.3.2.3) tells us
“the default for the size of the unit in default user space (1/72 inch) is
approximately the same as a point (pt), a unit widely used in the printing
industry. It is not exactly the same; there is no universal definition of a point.”
In short, 1 in. = 25.4 mm = 72 user units (which roughly corresponds to 72 pt).
By default 72 user units are 1 inch, but this default can be changed by defining a UserUnit.
Coordinate system: orientation
The second FAQ entry you have to read is: How should I interpret the coordinates of a rectangle in PDF?
Let me just copy/paste the image:
Coordinate system: origin
Finally, you have to read: Where is the origin (x,y) of a PDF page?
After reading the previous question, you might assume that the lower-left corner corresponds with the coordinate (0, 0), but that's not always true.
Why your question can't be answered
You claim that you are presenting the PDF as an image, and that you can retrieve coordinates as pixel coordinates, e.g. the 80th pixel in row 300 of all the pixel rows. However, if no one knows at which resolution the PDF is rendered when you converted the PDF (vector data) to a raster image, no one can tell you how the user units relate to pixels. That's something only you can know.
So please read the answers to the questions listed above carefully, and you'll be able to do the necessary Math.
I'm currently successfully adding text to a PDF using iTextSharp's ShowTextAligned method. The method looks like this (C#):
public void ShowTextAligned(
int alignment,
string text,
float x,
float y,
float rotation
)
However, it is unclear where the anchor point is for the text we're making. We provide x and y, but does these correspond to the upper left corner of the text rectangle, the lower left corner, or something else? Also is this impacted by line spacing?
I looked at the documentation at this website, but it isn't very explanatory. See PdfContentByte Class / PdfContentByte Methods / ShowTextAligned Method.
Obviously the anchor point depends on the kind of alignment. It does not make sense to say you right-align if your anchor point is at the left side of the text.
Furthermore, text operations usually align relative to the baseline.
Thus:
For left aligned text the anchor point is the left-most point of the text baseline.
For center aligned text the anchor point is the middle point of the text baseline.
For right aligned text the anchor point is the right-most point of the text baseline.
More visually:
This has been generated using:
[Test]
public void ShowAnchorPoints()
{
Directory.CreateDirectory(#"C:\Temp\test-results\content\");
string dest = #"C:\Temp\test-results\content\showAnchorPoints.pdf";
using (Document document = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(dest, FileMode.Create, FileAccess.Write));
document.Open();
PdfContentByte canvas = writer.DirectContent;
canvas.MoveTo(300, 100);
canvas.LineTo(300, 700);
canvas.MoveTo(100, 300);
canvas.LineTo(500, 300);
canvas.MoveTo(100, 400);
canvas.LineTo(500, 400);
canvas.MoveTo(100, 500);
canvas.LineTo(500, 500);
canvas.Stroke();
ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, new Phrase("Left aligned"), 300, 500, 0);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_CENTER, new Phrase("Center aligned"), 300, 400, 0);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT, new Phrase("Right aligned"), 300, 300, 0);
}
}
Using the pdfsharp.net library -- Im trying to load a big background jpg then on top of it write some text at a 90 degree angle. then save as a pdf
Why does my c# code below not work.
using System.Diagnostics;
using System.IO;
using System.Drawing;
using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using System.Drawing.Imaging;
namespace test
{
class Program
{
static void Main(string[] args)
{
PdfDocument myDoc = new PdfDocument();
PdfPage myPage = myDoc.AddPage();
myPage.Size = PdfSharp.PageSize.A4;
XGraphics g = XGraphics.FromPdfPage(myPage);
XImage image = XImage.FromFile(#"myjpg.jpg");
g.DrawImage(image, 0, 0, myPage.Width, myPage.Height);
XFont font = new XFont("Verdana", 20, XFontStyle.BoldItalic);
g.RotateAtTransform(90,new XPoint(0,0));
g.DrawString("test text!", font, XBrushes.Black, new XRect(0, 0, 200, 50), XStringFormats.Center);
myDoc.Save(#"test.pdf");
Process.Start(#"test.pdf");
}
}
}
Just a wild guess: your rotating at (0,0) - maybe you're rotating the text out of the page. Just presuming you see the picture but not the text.
See here for a working sample that uses rotation:
http://www.pdfsharp.net/wiki/XForms-sample.ashx
Center of rotation is not (0,0) in the sample.
If my guess is wrong, please provide more information what your code does.