3

I am using iText to read a pdf file. I have 20 Acro text fields in my pdf with different fillColor properties. I tried to read the properties but could not able to read. Is there any way we can get the fields which have a particular color as their fillcolor property in java?

EDIT: I created acro fields in the pdf using the following Adobe Javascript

   var oFld = this.addField("nameOfField", "button", 0, fldRect);
    if (oFld != null) {
        oFld.buttonSetCaption("");
        oFld.borderStyle = border.s;
        oFld.fillColor = color.gray;
        oFld.textColor = color.white;
        oFld.lineWidth = 1;
    }

UPDATE:

now I am able to read the color properties.

Am not sure whether it is the right way to do it or not?

  if(dict.getAsDict(PdfName.MK).get(PdfName.BG) !=null){
            if(dict.getAsDict(PdfName.MK).get(PdfName.BG).toString().trim().equals("     
    [0.0, 1.0, 0.0]")){
                System.out.println(entry.getKey());
                System.out.println("Green");
            }
            if(dict.getAsDict(PdfName.MK).get(PdfName.BG).toString().trim().equals("
        [1.0, 0.0, 0.0]")){
                System.out.println(entry.getKey());
                System.out.println("Red");
            }

        }
MaheshVarma
  • 2,081
  • 7
  • 35
  • 58
  • Please provide the PDF in question. Just to make sure, that Javascript has been applied to the PDF *before* iText handels it, and you do not expect iText to execute the Javascript, do you? – mkl Nov 25 '13 at 10:07
  • *the right way to do it or not* - well, checking with string comparisons is **not** the right way. Those are numbers and should be checked as numbers. Furthermore your initial `if` clause `if(dict.getAsDict(PdfName.MK).get(PdfName.BG) !=null)` fails in the absence of an **MK** dictionary. – mkl Nov 25 '13 at 12:23
  • Thanks for pointing out, if(ict.getAsDict(PdfName.MK)!=null) should avoid that null pointer exception and about the comparison, Should I iterate through [1.0, 0.0, 0.0] and compare each number or how can I do the number comparison? @mkl – MaheshVarma Nov 25 '13 at 12:43
  • The value of `PdfName.BG` is a (direct or indirect) array. Thus, get it as an array. Then you can iterate. Keep in mind, though, that the number of array elements may differ. @Bruno's answer contains the relevant information. – mkl Nov 25 '13 at 12:49
  • @mkl I am using the following code to compare colors. http://stackoverflow.com/questions/20193997/converting-rgb-values-into-color – MaheshVarma Nov 25 '13 at 13:57
  • The code there nowhere mentions string comparisons. – mkl Nov 25 '13 at 14:00
  • I pass the RGB values of array to the method then it returns the color name as string. – MaheshVarma Nov 25 '13 at 14:02
  • But BG does not necessarily contain RGB values. CMYK might also be in there. Or Grayscale. – mkl Nov 25 '13 at 14:11
  • As per my requirement I get only red or green – MaheshVarma Nov 25 '13 at 14:12
  • In that case you may succeed with that code. – mkl Nov 25 '13 at 15:22

1 Answers1

6

Chapter 8 of my book discusses AcroForm fields from a rather high level. If you want to dig deeper, you need chapter 13. On page 449, table 13.11 lists the different AcroFields.Item methods. As you know a form field is described using a form dictionary. The visual representation(s) of a field is (or are) described using one or more widget annotations. You're looking for a property of the appearance, so you need the annotation dictionary.

You also know that the field dictionary and the widget dictionary are often merged when one field corresponds with one widget annotation, and that's why the AcroFields.Item class has a method called getMerged(). For every widget annotation of a specific field, it returns the merged properties of the field and the widget annotation.

That's the theory. Let's look at an example: InspectForm

Map<String,AcroFields.Item> fields = form.getFields();
AcroFields.Item item;
PdfDictionary dict;
int flags;
for (Map.Entry<String,AcroFields.Item> entry : fields.entrySet()) {
    out.write(entry.getKey());
    item = entry.getValue();
    dict = item.getMerged(0);
    // inspect dict
}

In the example, we inspect the field flags (/FF), which are properties of the field dictionary. You are interested in appearance characteristics, so I guess you'll want to inspect the /MK entry, which is (ISO-32000-1 Table 188):

An appearance characteristics dictionary (see Table 189) that shall be used in constructing a dynamic appearance stream specifying the annotation’s visual presentation on the page. The name MK for this entry is of historical significance only and has no direct meaning.

You'll need to look at table 189 to find out the specific attributes you want:

R integer (Optional): The number of degrees by which the widget annotation shall be rotated counterclockwise relative to the page. The value shall be a multiple of 90. Default value: 0.

BC array (Optional): An array of numbers that shall be in the range 0.0 to 1.0 specifying the colour of the widget annotation’s border. The number of array elements determines the colour space in which the colour shall be defined: 0 No colour; transparent 1 DeviceGray 3 DeviceRGB 4 DeviceCMYK

BG array (Optional): An array of numbers that shall be in the range 0.0 to 1.0 specifying the colour of the widget annotation’s background. The number of array elements shall determine the colour space, as described for BC.

CA text string (Optional; button fields only): The widget annotation’s normal caption, which shall be displayed when it is not interacting with the user. Unlike the remaining entries listed in this Table, which apply only to widget annotations associated with pushbutton fields (see Pushbuttons in 12.7.4.2, “Button Fields”), the CA entry may be used with any type of button field, including check boxes (see Check Boxes in 12.7.4.2, “Button Fields”) and radio buttons (Radio Buttons in 12.7.4.2, “Button Fields”).

RC text string (Optional; pushbutton fields only): The widget annotation’s rollover caption, which shall be displayed when the user rolls the cursor into its active area without pressing the mouse button.

AC text string (Optional; pushbutton fields only): The widget annotation’s alternate (down) caption, which shall be displayed when the mouse button is pressed within its active area.

When you ask for the fill color, I assume that you're referring to the background color, which means you'll have to look at the BC entry for the colorspace, and at the BG entry for the actual color value.

Community
  • 1
  • 1
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • I used dict.getAsDict(PdfName.MK).get(PdfName.BG) to get the color value, you mentioned table 189 to find out the specific attributes, Where I can find the table ? Is it in PDF spec? – MaheshVarma Nov 25 '13 at 11:41
  • Yes, and I copied it entirely in my answer: R, BC, BG, CA, RC and AC are the entries listed in that table. Suppose that BC is 3, than BG will be an array of three values: a red, green and yellow value expressed as a number between 0 and 1. – Bruno Lowagie Nov 25 '13 at 12:46
  • Thanks for clear explanation. Now I am able to read the color properties of acro fields. I updated my question. @BrunoLowagie – MaheshVarma Nov 25 '13 at 12:50