py-pdf / pypdf

A pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files
https://pypdf.readthedocs.io/en/latest/
Other
8.41k stars 1.42k forks source link

Adobe Requires Annotation Flag for Printing Annotations #2896

Closed MarleTangible closed 1 month ago

MarleTangible commented 1 month ago

It's more of an observation than a bug actually. When a FreeText annotation is added a sample PDF file, adobe shows the annotation but despite selecting "document and markups" for printing options, the annotations are not printed. Strangely enough adding a flag value of "4" resolves the issue.

Following example adds an annotation but it doesn't print.

from pypdf import PdfReader, PdfWriter
from pypdf.annotations import FreeText

writer = PdfWriter()
writer.add_blank_page(width=1000, height=1000)
annotation = FreeText(text='Hello', rect=(100, 200, 300, 400))

# Adding a flag value of 4 solves the issue for some reason.
annotation.flags = 4

writer.add_annotation(page_number=0, annotation=annotation)

with open("annotated-pdf.pdf", "wb") as fp:
    writer.write(fp)

Here's the annotation created with the flag. Removing the flag or using any other value caused the annotation to now show up when printing.

{
    '/Subtype': '/FreeText',
    '/Rect': RectangleObject([100, 200, 300, 400]),
    '/Contents': 'Hello',
    '/DS': 'font: Helvetica 14pt;text-align:left;color:#000000',
    '/DA': '0.0 0.0 0.0 rg',
    '/C': [1, 1, 1],
    '/P': IndirectObject(4, 0, 2825432839120),
    '/F': 4
}

The annotation only shows up for printing if a flag value of 4 is applied. Maybe there is something else at play but I couldn't make it work any other way. I added a comment via adobe and reviewed its properties and then added removed some until I eliminated every field except the flag.

image

MarleTangible commented 1 month ago

Realized that AnnotationDictionary class sets the default value as AnnotationFlag(0) and constants.py defines the options as below, which requires "4" for printable annotations.

class AnnotationFlag(IntFlag):
    """See §12.5.3 "Annotation Flags"."""

    INVISIBLE = 1
    HIDDEN = 2
    PRINT = 4
    NO_ZOOM = 8
    NO_ROTATE = 16
    NO_VIEW = 32
    READ_ONLY = 64
    LOCKED = 128
    TOGGLE_NO_VIEW = 256
    LOCKED_CONTENTS = 512

Would it be possible to add a note about the print option in the annotation documentation? Something similar to the transfer_rotation_to_content() notes.

annotation.flags = 4 # Make the annotation printable.
pubpub-zz commented 1 month ago

@MarleTangible thanks for the comment. Can you propose a PR?

MarleTangible commented 1 month ago

@pubpub-zz Thank you for the quick reply. Created https://github.com/py-pdf/pypdf/pull/2897 for the issue.