Reputation: 95
I am using iTextSharp version 5.0.
For my projet, I need to copy my pdf document into another pdf document using pdfWriter. I can't use pdfCopy nor pdfStamper.
So all the annotations get lost during this operation.
To begin, I started to find how to get the annotations of the "pencil comment drawing markup" as shown below on adobe reader UI:
For my tests, I am using this pdf document with a drawing markup I added my self: https://easyupload.io/3c6i1g
I found how to get the annotation dictionary:
Dim pdfReader As New PdfReader(pdfPath)
Dim page As PdfDictionary = pdfReader.GetPageN(0)
Dim annots As PdfArray = page.GetAsArray(PdfName.ANNOTS)
If annots IsNot Nothing Then
For i = 0 To annots.Size - 1
Dim annotDict As PdfDictionary = annots.GetAsDict(i)
Dim annotContents As PdfString = annotDict.GetAsString(PdfName.CONTENT)
Dim annotSubtype As PdfString = annotDict.GetAsString(PdfName.SUBTYPE)
Dim annotName As PdfString = annotDict.GetAsString(PdfName.T)
Next
End If
When the loop is parsing my comment the annotName variable returns my name, so I am sure to parse the annotation I am looking for but the annotSubtype is equal Nothing, how is that possible? According to the pdf specification at section 12.5.2 table 1666 (https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf), the subtype parameter is required, so wouldn't it means this should not be at nothing?
Also, how can I get the image related to this annotation? I thought it would be stored in the content of the annotation dictionary but this is also returning nothing in the code above...
about why I can't use pdfStamper at the first place : one of the page of my pdf document must be resized (downscaled) in order to add some text at the bottom of the page, so I must use pdfWriter for that.
Question: How can I get the drawn line of a comment annotation with iTextSharp 5.0?
Upvotes: 1
Views: 1080
Reputation: 96064
There are a lot of single questions in your post...
When the loop is parsing my comment the
annotName
variable returns my name, so I am sure to parse the annotation I am looking for but theannotSubtype
is equalNothing
, how is that possible?According to the pdf specification at section 12.5.2 table 1666 (https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf), the subtype parameter is required, so wouldn't it means this should not be at nothing?
According to table 164 in section 12.5.2 of ISO 32000-1, the Subtype entry indeed is required, but it also specified to be a name while you try to retrieve a string instead:
Dim annotSubtype As PdfString = annotDict.GetAsString(PdfName.SUBTYPE)
As the Subtype entry of that annotation in your PDF correctly is a name, GetAsString
returns Nothing
.
Thus, call GetAsName
instead and expect a PdfName
return type.
Also, how can I get the image related to this annotation? I thought it would be stored in the content of the annotation dictionary but this is also returning nothing in the code above...
The Contents entry is specified in the same table as above to be optional and (if present) to have a text string value containing a Text that shall be displayed for the annotation or, if this type of annotation does not display text, an alternate description of the annotation’s contents in human-readable form. As the annotation merely is a scribble, what should the annotation have as Contents value?
As your annotation actually is an Ink annotation, you can find the representation of the scribble in the required InkList and optional BS entries of the annotation, see table 182 of section 12.5.6.13 of ISO 32000-1.
The value of InkList is An array of n arrays, each representing a stroked path. Each array shall be a series of alternating horizontal and vertical coordinates in default user space, specifying points along the path. When drawn, the points shall be connected by straight lines or curves in an implementation-dependent way.
The value of the BS (if present) is A border style dictionary (see Table 166) specifying the line width and dash pattern that shall be used in drawing the paths.
Beware, though: The annotation dictionary’s AP entry, if present, takes precedence over the InkList and BS entries. And in your PDF the annotation has an appearance entry. So the actually displayed content is that of the Normal appearance stream which contains vector graphics instructions drawing your scribble.
about why I can't use pdfStamper at the first place : one of the page of my pdf document must be resized (downscaled) in order to add some text at the bottom of the page, so I must use pdfWriter for that.
First of all, this only means that you have to do something special to that special page, there is no need to damage all pages by copying them with a PdfWriter
. You could manipulate that single page in a separate document, then use PdfCopy
to copy the pages before that page from the original PDF, then that page from the separate PDF, and then all pages after that page from the original again.
Thus, you'd only have to fix the annotations of that special page, the annotations on the other pages could remain untouched.
Furthermore, you can even use the PdfStamper
if you are ready to use low level iText routines. In particular before stamping you can apply the static PdfReader
method GetPageContent
to the page dictionary of the special page to retrieve the page content as byte array, build a new byte array from it in which you prepend an affine transformation which does the downscaling, and set the new byte array as content of the page in question using the SetPageContent
method of the underlying PdfReader
Even in this scenario, though, you'd have to adjust the annotation coordinates (both of their rectangles and of other coordinates like the InkList in your case)...
Question: How can I get the drawn line of a comment annotation with iTextSharp 5.0?
See above, the annotation of the scribble is an Ink annotation and the drawn path is specified in the InkList and BS entries of its dictionary and additionally instantiated in its normal appearance stream.
Upvotes: 1