Repository navigation
ops: destroy the pixels under a redaction - #81
Merged
Merged
Conversation
ISO 32000-1 12.5.6.23 is explicit:
If a portion of an image is contained in a redaction region, that portion
of the image data shall be destroyed; clipping or image masks shall not be
used to hide that data.
Redact refused every region a picture was drawn across, which for a scanned
page — one picture — is everything. The samples under the region are now
overwritten and the picture is written back.
What it does that to is a picture whose samples are PLAIN (one the reader has
already unfiltered), eight bits a component, DeviceGray or DeviceRGB, drawn
UPRIGHT and drawn ONCE. The rest are refused by their own names, each with its
reason: a JPEG would have to be decoded and re-encoded, which is a size and a
quality question of its own; a turned picture cannot be mapped into its samples
by the box it covers without destroying more than was asked for (extract
v0.11.0's Image.Matrix was added for exactly this); a picture drawn twice would
be blanked for both placements; an inline image has nothing to write back to;
an /ImageMask, /SMask, /Mask or /Decode changes what a sample means; an
/Indexed zero is the palette's FIRST colour, which may be white.
⛔⛔ THE PAGE'S RESOURCES ARE REBUILT, NOT COPIED. Copying them would have put
the original picture into the file beside the blanked one, referenced by
nothing and holding every pixel the redaction promised to remove -- defect #74
one object along. The test walks EVERY object of the written file and decodes
it, because a picture's samples are compressed and a raw grep cannot see them.
decorate goes through the same function, or a page both redacted and stamped
would have had its original picture put back, silently.
⛔ The sample grid counts DOWN while the page counts UP: row zero is the
picture's top row and v runs from its bottom edge. Reading one for the other
blanks the mirror image of what was asked for, which looks like a redaction
until somebody compares it with the page — so the test gives every row its own
colour and names which must survive. A region ending part way into a sample
destroys all of it: a third of a secret is a secret.
Closes #80 for the plain case; the JPEG half stays open there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ISO 32000-1, 12.5.6.23:
Redactrefused every region a picture was drawn across — which, for a scannedpage, is every region there is. It now overwrites the samples under the region
and writes the picture back.
What it can do that to
A picture whose samples are plain (one the reader has already unfiltered),
eight bits a component,
DeviceGrayorDeviceRGB, drawn upright and drawnonce on the page.
Everything else is refused by its own name, with the reason, at
Redact—where a caller can still choose another region or another tool — because one
function plans the change for both the check and the write:
/Filter)Do, so blanking one placement blanks the others, elsewhere on the page/ImageMask,/SMask,/Mask,/Decode/Indexed,/ICCBased, …extractv0.11.0'sImage.Matrixwas added for the upright test; this PR bumpsto it.
Two traps, both with a test that would catch them again
⛔ The page's
/Resourcesare rebuilt, not copied. Copying them would haveleft the original picture in the file beside the blanked one — referenced by
nothing, holding every pixel the redaction promised to remove. That is defect
#74 one object along. The test walks every object of the written file and
decodes it, because samples are compressed and a raw grep cannot see them.
decorategoes through the same function, or a page both redacted and stampedwould have had its original picture put back, silently.
⛔ The sample grid counts down while the page counts up. Row zero is the
picture's top row and
vruns from its bottom edge. Reading one for the otherblanks the mirror image of what was asked for, which looks like a redaction
until somebody compares it with the page — so the test gives every row its own
colour and names which rows must survive. A region ending part way into a sample
destroys all of it: a third of a secret is a secret.
Gate:
ok github.com/go-pdfkit/ops 13.8s coverage: 100.0% of statements,covblocks: 0 blocks uncovered.Closes #80 for the plain case; the JPEG half stays open there.
🤖 Generated with Claude Code