Hot questions for Using PDFBox in xfdf

Question:

I have an XFDF files contain some Annotations but not Fields, I would like to know is it able to import those Annotations into PDF file with PDFBox

I have tried to import the XFDF into PDF in Acrobat Reader DC and it's successful to show the imported annotations. However it is not success to show the annotations via used the function importFDF in PDAcroForm. It only import the fields but not annotations.

below is my sample XFDF

    <?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<fields />
<annots>
    <ink page="0" rect="414.755559,308.987191,564.755559,365.356617" color="#000000" flags="print" name="a74a6f8a-4149-d913-6ee6-34ba434bc254" title="annotationTest" subject="Signature" date="D:20190808175939+08'00'" creationdate="D:20190808175827+08'00'">
        <inklist>
            <gesture>415.23,342.9;415.23,342.9;417.62,345.77;422.4,349.11;441.98,357.24;456.79,361.53;470.17,364.88;471.12,364.88;471.6,362.97;468.74,355.8;464.44,346.25;456.79,333.35;440.07,314.72;432.91,310.9;429.56,309.46;429.09,309.46;427.65,312.81;427.65,316.15;429.09,319.02;432.91,322.36;445.81,324.27;454.41,323.8;463,320.45;472.56,317.11;488.32,315.2;499.31,315.68;505.52,318.06;509.82,320.45;514.12,322.36;514.6,322.36;515.55,322.36;517.94,322.36;526.06,322.36;530.36,322.36;535.14,322.36;539.44,322.36;541.83,322.36;542.78,322.36;543.26,322.36;544.69,322.36;546.6,322.84;548.51,322.84;549.47,322.84;550.42,323.8;552.34,325.23;553.29,325.71;554.25,326.66;554.72,327.14;556.63,328.1;559.98,329.05;564.28,330.48</gesture>
        </inklist>
    </ink>
    <circle page="0" rect="464.76803,505.088095,546.727124,576.052676" color="#FF8D00" flags="print" name="96f7f067-0811-a87f-3d94-0b654a720d7d" title="annotationTest" subject="Ellipse" date="D:20190808175825+08'00'" width="6" creationdate="D:20190808175813+08'00'"/>
    <polygon page="0" rect="184.107608,217.431165,445.578111,277.002438" color="#E44234" flags="print" name="8523798b-3d79-d612-40bb-bcdec2789dcd" title="annotationTest" subject="Polygon" date="D:20190808175810+08'00'" style="cloudy" interior-color="#92E8E8" width="9" opacity="0.58" creationdate="D:20190808175742+08'00'" intensity="2">
        <vertices>191.9,269.21;438.78,270.21;433.78,225.23;191.9,224.23;190.9,224.23;191.9,269.21</vertices>
    </polygon>
    <freetext page="0" rect="376.81193,778.184946,500.283994,807.936941" flags="print" name="373b558a-4892-5fb4-a9aa-b4d7175d3966" title="annotationTest" subject="Free text" date="D:20190808175721+08'00'" width="0" creationdate="D:20190808175700+08'00'" TextColor="#00CC63" FontSize="17">
        <contents>Some words...</contents>
        <defaultappearance>0 0 0 rg /Arial 17 Tf</defaultappearance>
        <defaultstyle>font: Arial 17pt; text-align: left; color: #00CC63</defaultstyle>
    </freetext>
    <square page="0" rect="196.901725,719.980841,436.781998,752.964378" color="#E44234" flags="print" name="31250d16-7ee0-c34e-027c-5e11e66cf2b1" title="annotationTest" subject="Rectangle" date="D:20190808175655+08'00'" interior-color="#FFC67B" opacity="0.23" creationdate="D:20190808175653+08'00'"/>
    <link page="0" rect="36.507,555.18,136.6,581.705" color="#000000" flags="print" name="null" title="null" subject="null" date="D:20190808175651+08'00'" width="0" style="solid"/>
</annots>
<pages>
    <defmtx matrix="1.3333333333333333,0,0,-1.3333333333333333,0,1122.559973" />
</pages>
</xfdf>

Or any other library recommended? Many thanks.


Answer:

After loaded xfdf file, get the COSObject from FDAnnotation and then use it to create a PDAnnotation

PDAnnotation pdfannot = PDAnnotation.createAnnotation(fdfannot.getCOSObject());

And then add to page

List<PDAnnotation> pdfannots = new ArrayList<PDAnnotation>;
pdfannots.add(pdfannot);
page.setAnnotations(pdfannots);

Save it, and you will see the annotations on the PDF

Question:

After imported XFDF to FDFAnnotation and converted to PDAnnotation, I find that the font color of PDAnnotationFreeText is missing.

<freetext page="0" rect="376.81193,778.184946,500.283994,807.936941" flags="print" name="373b558a-4892-5fb4-a9aa-b4d7175d3966" title="wwh" subject="Free text" date="D:20190808175721+08'00'" width="0" creationdate="D:20190808175700+08'00'" TextColor="#00CC63" FontSize="17">
    <contents>English</contents>
    <defaultappearance>0 0 0 rg /Arial 17 Tf</defaultappearance>
    <defaultstyle>font: Arial 17pt; text-align: left; color: #00CC63</defaultstyle>
</freetext>

and this is the details after import to FDFAnnotation

COSDictionary{
    COSName{Type}:COSName{Annot};
    COSName{Page}:COSInt{0};
    COSName{M}:COSString{D:20190808175721+08'00'};
    COSName{F}:COSInt{4};
    COSName{NM}:COSString{373b558a-4892-5fb4-a9aa-b4d7175d3966};
    COSName{Rect}:COSArray{COSFloat{376.81192};COSFloat{778.18494};COSFloat{500.284};COSFloat{807.93695};};
    COSName{T}:COSString{wwh};
    COSName{CreationDate}:COSString{D:20190808175700+08'00'};
    COSName{Subj}:COSString{Free text};
    COSName{IT}:COSName{};
    COSName{Contents}:COSString{English};
    COSName{Subtype}:COSName{FreeText};
    COSName{Q}:0;
    COSName{DA}:COSString{0 0 0 rg /Arial 17 Tf};
    COSName{DS}:COSString{font: Arial 17pt; text-align: left; color: #00CC63};
}

I have extract the color hex code and tried to convert to PDColor

int c = Integer.parseInt("#00CC63".substring(1), 16);
float r = ((c & 0xFF0000) >> 16) / 255f;
float g = ((c & 0x00FF00) >>  8) / 255f;
float b = ((c & 0x0000FF) >>  0) / 255f;
PDColor pdc = new PDColor( new float[] { r, g, b }, PDDeviceRGB.INSTANCE);

But the PDColor is only change the background color, not my expectation. May I know how to set the font color on it?

This is my sample file: https://1.bitsend.jp/download/c10903041b8af47195daeef1f471a366.html


Answer:

This will be fixed in PDFBox 2.0.17, the color of the /DS entry (annotation.getDefaultStyleString()) will be considered too and will have priority over the color in the /DA entry (annotation.getDefaultAppearance()). The new implementation can be seen here, a snapshot is available here.

Question:

In pdfbox 1.8 there was a class "ImportXFDF", as you can see here: pdfbox API 1.8.11 for ImportXFDF. It was very easy to import the data from an XFDF File into the PDF fields with the importFDF-Method.

With the new version 2.0 the class was removed, and I can't find where the functionality is now (I hope it was not dropped?). pdfbox API 2.0.1 The Migration Guide on the website doesn't tell anything about this function.

Anyone knows how to import an XFDF into an PDF file now? Thanks for your help!


Answer:

Okay, I checked out the original implementation of ImportXFDF which is very small and copied it into my code:

public void importFDF(PDDocument pdfDocument, FDFDocument fdfDocument) throws IOException
{
  PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
  PDAcroForm acroForm = docCatalog.getAcroForm();
  acroForm.setCacheFields(true);
  acroForm.importFDF(fdfDocument);
}

Works very well with the 2.0 version :)