Description
Repeated redacting of same areas removes old visual redaction rectangles, regression of !115. Labelled as feature, because it is only a visual annoyance without safety impication and a workaround exists: not draw rectangles on top of old redactions, or to redraw multiple redaction rectangles.
How to reproduce?
- Redact a document with some rectangles
- Save it
- Continue redacting, drawing new redaction rectangles touching old redaction rectangles
- Save it
- Observe that the old redaction rectangles (which are just drawings now), are removed
Implementation
1. Detection of old redaction rectangles
Maybe detect old redaction rectangles and redraw them after applying the redaction. But, that is indeed a little difficult, because rectangles may express sensitive information, e.g.,
hello
is only drawn with black rectangles and still conveys a message.
Redaction rectangle information with PyMuPDF
{'items': [('re', Rect(242.28219604492188, 110.953125, 322.3974304199219, 137.4697265625), 1)],
'type': 'fs',
'even_odd': False,
'fill_opacity': 1.0,
'fill': (0.0, 0.0, 0.0),
'rect': Rect(242.28219604492188, 110.953125, 322.3974304199219, 137.4697265625),
'seqno': 7,
'layer': '',
'level': 1,
'stroke_opacity': 1.0,
'color': (0.0, 0.0, 0.0),
'width': 1.0,
'lineCap': (0, 0, 0),
'lineJoin': 0.0,
'closePath': False,
'dashes': '[] 0'}
Thus, this option would likely come with decreased security.
2. Keep record of redactions during a session
During a session (redact ..., save, redact ..., save, redact ..., save, ...), the issue could be solved in two ways. Both involve keeping track of all redactions.
-
apply all redactions only always on the first version
- this is may be fine, but increases the load and is more error-prune.
-
apply all redactions always on the current version
- this sounds like best option. It will redact the old redactions and draw others on top of them
-
apply only the redactions of the current step, but redraw redaction rectangles of previous steps if they have been removed.
Pseudo code
old_drawings = {page.number: page.get_drawings() for page in document}
old_redactions = {page.number: page.old_redactions for page in document}
document.apply_redactions(...)
def matches(redaction, drawing):
return redaction.rect == drawing.rect # approximately, check also color, etc.
def draw(drawing):
pymupdf.shape ...
for page in document:
new_drawings = page.get_drawings()
for redaction in old_redactions:
for drawing in new_drawings:
if matches(redaction, drawing):
new_drawings.remove(drawing)
break
else:
for drawing in old_drawings[page.number]:
if matches(redaction, drawing):
draw(drawing)
old_drawings[page.number].remove(drawing)
break
I tend to prefer the safer and less error-prune approach of 2. A difficulty may be in the level of allowed customization, as seen in #11, but with 2. it shouldn’t be an issue (to be tested ...)
3. Keep record of redactions in redacted documents
Somehow, safe the information of the redactions inside the document, not only via drawings. Then, these rectangles could be redrawn also like in 2. It would require to safe the annotation parameters (size, color, etc.) inside the PDF file.
## Description
Repeated redacting of same areas removes old visual redaction rectangles, regression of !115. Labelled as feature, because it is only a visual annoyance without safety impication and a workaround exists: not draw rectangles on top of old redactions, or to redraw multiple redaction rectangles.
## How to reproduce?
1. Redact a document with some rectangles
2. Save it
3. Continue redacting, drawing new redaction rectangles touching old redaction rectangles
4. Save it
5. Observe that the old redaction rectangles (which are just drawings now), are removed
## Implementation
### 1. Detection of old redaction rectangles
Maybe detect old redaction rectangles and redraw them after applying the redaction. But, that is indeed a little difficult, because rectangles may express sensitive information, e.g.,

is only drawn with black rectangles and still conveys a message.
<details><summary>Redaction rectangle information with PyMuPDF</summary>
```py
{'items': [('re', Rect(242.28219604492188, 110.953125, 322.3974304199219, 137.4697265625), 1)],
'type': 'fs',
'even_odd': False,
'fill_opacity': 1.0,
'fill': (0.0, 0.0, 0.0),
'rect': Rect(242.28219604492188, 110.953125, 322.3974304199219, 137.4697265625),
'seqno': 7,
'layer': '',
'level': 1,
'stroke_opacity': 1.0,
'color': (0.0, 0.0, 0.0),
'width': 1.0,
'lineCap': (0, 0, 0),
'lineJoin': 0.0,
'closePath': False,
'dashes': '[] 0'}
```
</details>
Thus, this option would likely come with decreased security.
### 2. Keep record of redactions during a session
During a session (redact ..., save, redact ..., save, redact ..., save, ...), the issue could be solved in two ways. Both involve keeping track of all redactions.
1. apply all redactions only always on the first version
- this is may be fine, but increases the load and is more error-prune.
2. apply all redactions always on the current version
- this sounds like best option. It will redact the old redactions and draw others on top of them
3. apply only the redactions of the current step, but redraw redaction rectangles of previous steps if they have been removed.
<details><summary>Pseudo code</summary>
```py
old_drawings = {page.number: page.get_drawings() for page in document}
old_redactions = {page.number: page.old_redactions for page in document}
document.apply_redactions(...)
def matches(redaction, drawing):
return redaction.rect == drawing.rect # approximately, check also color, etc.
def draw(drawing):
pymupdf.shape ...
for page in document:
new_drawings = page.get_drawings()
for redaction in old_redactions:
for drawing in new_drawings:
if matches(redaction, drawing):
new_drawings.remove(drawing)
break
else:
for drawing in old_drawings[page.number]:
if matches(redaction, drawing):
draw(drawing)
old_drawings[page.number].remove(drawing)
break
```
</details>
I tend to prefer the safer and less error-prune approach of 2. A difficulty may be in the level of allowed customization, as seen in #11, but with 2. it shouldn’t be an issue (to be tested ...)
### 3. Keep record of redactions in redacted documents
Somehow, safe the information of the redactions inside the document, not only via drawings. Then, these rectangles could be redrawn also like in 2. It would require to safe the annotation parameters (size, color, etc.) inside the PDF file.