-
Notifications
You must be signed in to change notification settings - Fork 647
Closed
Labels
not a bugnot a bug / user error / unable to reproducenot a bug / user error / unable to reproduce
Description
Description of the bug
When creating redaction annotations with PyMuPDF, Adobe Acrobat always applies the redactions with a white fill, regardless of the fill color specified in the annotation or set using properties in app i.e. black.
How to reproduce the bug
Steps to Reproduce:
1. Use attached sample pdf as input file.
Run below code to generate redacted preview of pdf. Generated pdf will have red outline box and black fill seen when hovering over it.
```
import fitz
def force_red_outline(doc, annot):
"""
Replace /AP stream of a redact annotation with a red-outline box.
"""
rect = annot.rect
x0, y0, x1, y1 = rect
width = x1 - x0
height = y1 - y0
# Normal appearance (red outline only)
normal_stream = f"""
q
1 0 0 RG % Red stroke color
1 w % 1 point line width
0 0 {x1 - x0} {y1 - y0} re % Rectangle
S % Stroke only
Q
""".strip().encode()
# Rollover/hover appearance (black fill + red outline)
rollover_stream = f"""
q
0 0 0 rg % Black fill color
1 0 0 RG % Red stroke color
1 w % 1 point line width
0 0 {width} {height} re % Rectangle
B % Fill and stroke
Q
""".strip().encode()
# Create appearance dictionary with both normal and rollover states
ap_dict_normal = f"""<<
/Type /XObject
/Subtype /Form
/BBox [0 0 {width:.2f} {height:.2f}]
/Matrix [1 0 0 1 0 0]
/Resources << /ProcSet [/PDF] >>
/Length {len(normal_stream)}
>>"""
ap_dict_rollover = f"""<<
/Type /XObject
/Subtype /Form
/BBox [0 0 {width:.2f} {height:.2f}]
/Matrix [1 0 0 1 0 0]
/Resources << /ProcSet [/PDF] >>
/Length {len(rollover_stream)}
>>"""
# Add appearance streams to document
normal_xref = doc.get_new_xref()
rollover_xref = doc.get_new_xref()
# First create the dictionary objects
doc.update_object(normal_xref, ap_dict_normal)
doc.update_object(rollover_xref, ap_dict_rollover)
# Then add the stream content
doc.update_stream(xref=normal_xref, stream=normal_stream)
doc.update_stream(xref=rollover_xref, stream=rollover_stream)
# Set appearance dictionary with both normal and rollover states
ap_reference = f"<< /N {normal_xref} 0 R /R {rollover_xref} 0 R >>"
doc.xref_set_key(annot.xref, "AP", ap_reference)
doc.xref_set_key(annot.xref, "IC", "[0 0 0]") # Interior color: BLACK
doc.xref_set_key(annot.xref, "C", "[1 0 0]") # Border color: RED
if __name__ == "__main__":
pdf_file = 'input.pdf'
sanitize_file_path = 'output.pdf'
doc = fitz.open(pdf_file)
sanitized_content = [['Blue-sky printing', 'There are many reasons for using Prince. We will show you 8.', 'one:', ' [lang]', 'three:', ' [frame] columns', 'Prince supports [lang] so that programmers can', 'achieve effects not possible in HTML and CSS along.', 'For example, this document has a small script that auto-', 'matically generates a table of contents:', 'This document is laid out in two columns on the', 'first page. The next pages are more narrow and', 'therefore only has room for one column. The num-', 'ber of columns is automatically adjusted based on', 'the available width.', '[lang]......................1', 'More [lang] ...........1', '[frame] columns...............1', 'Styling pages.................1', '[frame] transforms.......... 1', 'Background images.....2', '[frame] selectors..............2', 'More transforms.........2', '4:', ' Styling pages', 'The second page of this document is different from the first: it’s up-', 'right and it has no background image. This is achieved by styling', 'pages instead of elements.', 'two:', ' More [lang]', 'This document lists 8 numbered features. Notice that the first', 'three features are numbered with spelled-out numbers, while', 'the rest use digits. This is achieved with a small script that ex-', 'changes digits for letters when the number is three or smaller.', '5:', ' [frame] transforms', '[frame] introduces transforms, which can be used to scale and'], ['Prince', 'rotate elements. «Prince» is rotated 90 degerees on the right.', 'Also, it has been moved to a margin box so that it appears out-', 'side the normal text flow.', '6:', ' Background images', 'The image on the right is used as the', 'background image on the first page.', 'There, only part of the image is visible.', 'This is achieved by carefully setting the', 'position and pixel-density of the image.', 'Also, notice how the background image is', '«bleeding»; it extends slightly outside the', 'page to avoid white edges when the paper', 'is cut.', '7:', ' [frame] selectors', 'Notice how every other item in our list of eight is in italics. This is achieved by', 'selecting and styling even-numbered items.', '8:', ' More transforms', 'Transforms can be applied to images as well as text. Below is the blue-sky background im-', 'age rotated at various angles.']]
page_count=0
for page in doc.pages():
text_blocks = page.get_text("dict", flags=fitz.TEXTFLAGS_TEXT)["blocks"]
text_blocks.sort(
key=lambda span: (span["bbox"][1], span["bbox"][0])
) # Sort by position
index = 0
for block in text_blocks:
for line in block.get("lines", []):
for span in line.get("spans", []):
if (
index >= len(sanitized_content[page_count])
or span["text"] == sanitized_content[page_count][index]
or span["text"] == " "
):
index += 1
continue # Skip if text is already correct
# Add redaction annotation that Adobe can recognize
x0, y0, x1, y1 = span["bbox"]
redact_rect = fitz.Rect(x0, y0, x1, y1)
redact_annot = page.add_redact_annot(redact_rect, text="", fill=(0, 0, 0), cross_out=False)
force_red_outline(doc, redact_annot)
index += 1
page_count += 1
doc.save(sanitize_file_path)
doc.close()
2. Open this saved pdf from above step using Adobe, ensure All tools > Redact a PDF > Set properties > Redacted Fill Area color is set to black.
3. Apply Redaction using Apply button, all redacted boxes turns white
4. If step 2 and 3 are repeated manually in Adobe on same pdf, you will see redacted boxes are in black.
Ask:
Is there any workaround to make fill color as black when apply redaction from Adobe till this bug is resolved?
### PyMuPDF version
1.26.3
### Operating system
MacOS
### Python version
3.11
Metadata
Metadata
Assignees
Labels
not a bugnot a bug / user error / unable to reproducenot a bug / user error / unable to reproduce