Skip to content

Commit 5a8ce70

Browse files
committed
Add commands
1 parent feb1658 commit 5a8ce70

14 files changed

Lines changed: 1165 additions & 0 deletions
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# TAGLINE
2+
3+
Apply a tracking-dot mask to a PDF before printing
4+
5+
# TLDR
6+
7+
**Apply** a mask and write **masked.pdf**
8+
9+
```deda_anonmask_apply [mask.json] [document.pdf]```
10+
11+
Shift the pattern by a fraction of an **inch**
12+
13+
```deda_anonmask_apply --xoffset [0.01] --yoffset [-0.02] [mask.json] [document.pdf]```
14+
15+
Change the **dot radius**
16+
17+
```deda_anonmask_apply --dotradius [0.005] [mask.json] [document.pdf]```
18+
19+
Draw the dots in **magenta** so they are easy to see
20+
21+
```deda_anonmask_apply --debug [mask.json] [document.pdf]```
22+
23+
# SYNOPSIS
24+
25+
**deda_anonmask_apply** [_options_] _mask_ _pdf_
26+
27+
# PARAMETERS
28+
29+
_mask_
30+
31+
> Mask file written by **deda_anonmask_create -r**, usually **mask.json**.
32+
33+
_pdf_
34+
35+
> PDF to stamp. The original file is not modified.
36+
37+
**--xoffset** _inches_, **--yoffset** _inches_
38+
39+
> Extra horizontal and vertical shift of the dot grid, in inches.
40+
41+
**--dotradius** _inches_
42+
43+
> Radius of each dot, in inches. The default is the toolkit's built-in radius.
44+
45+
**--debug**
46+
47+
> Draw magenta dots instead of yellow ones.
48+
49+
**-v**, **--verbose**
50+
51+
> Repeat to print more diagnostic detail.
52+
53+
# DESCRIPTION
54+
55+
**deda_anonmask_apply** reads a mask from **deda_anonmask_create** and stamps that dot pattern onto a copy of a PDF. It prints the offset, dot radius, and scale it used, then writes **masked.pdf** in the working directory. Print that file with a zero page margin, the same margin used for the calibration page.
56+
57+
Pages that contain white or light areas inside images need the **Wand** Python package, which binds to ImageMagick. Without it, those areas are left unmasked. The rest of the page is still processed.
58+
59+
# CAVEATS
60+
61+
The output path is always **masked.pdf** in the current directory. A file of that name is overwritten. The input PDF is not changed.
62+
63+
Alignment depends on the printer using the same margin as the calibration print. **--xoffset**, **--yoffset**, and **--dotradius** are the adjustments when the grid does not cover the printer's own dots. A mask built with **deda_anonmask_create --copy** reproduces a pattern instead of hiding one.
64+
65+
Yellow dots on a finished print are hard to see. **--debug** is the way to confirm placement before using yellow.
66+
67+
# HISTORY
68+
69+
**deda_anonmask_apply** is part of **DEDA**, written by **Timo Richter** and **Stephan Escher** and described in their **2018** paper on forensic analysis and anonymisation of printed documents.
70+
71+
# SEE ALSO
72+
73+
[deda_anonmask_create](/man/deda_anonmask_create)(1), [deda_create_dots](/man/deda_create_dots)(1), [deda_clean_document](/man/deda_clean_document)(1), [deda_parse_print](/man/deda_parse_print)(1)
74+
75+
# RESOURCES
76+
77+
```[Source code](https://github.com/dfd-tud/deda)```
78+
79+
<!-- verified: 2026-10-06 -->
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# TAGLINE
2+
3+
Build a calibration mask for printer tracking dots
4+
5+
# TLDR
6+
7+
**Write** the calibration page
8+
9+
```deda_anonmask_create -w```
10+
11+
**Read** a scan of that page and write the mask
12+
13+
```deda_anonmask_create -r [calibration.png]```
14+
15+
Copy the printer's dot pattern into the mask **instead of anonymising** it
16+
17+
```deda_anonmask_create -r [calibration.png] --copy```
18+
19+
# SYNOPSIS
20+
21+
**deda_anonmask_create** **-w** [_options_]
22+
23+
**deda_anonmask_create** **-r** _file_ [_options_]
24+
25+
# PARAMETERS
26+
27+
**-w**, **--write**
28+
29+
> Write a calibration PDF to **testpage.pdf** in the working directory. Mutually exclusive with **-r**.
30+
31+
**-r** _file_, **--read** _file_
32+
33+
> Read a scan of a printed calibration page and write **mask.json**. Mutually exclusive with **-w**.
34+
35+
**-c**, **--copy**
36+
37+
> Store the printer's own dot pattern in the mask instead of an anonymising pattern. Used with **-r**.
38+
39+
**-v**, **--verbose**
40+
41+
> Repeat to print more diagnostic detail.
42+
43+
# DESCRIPTION
44+
45+
**deda_anonmask_create** is the first half of DEDA's print anonymisation. **-w** writes **testpage.pdf**. Print that file with no page margin, scan the printout at about **300** dpi in a lossless format, and pass the scan to **-r**. The command writes **mask.json**, which **deda_anonmask_apply** stamps onto later PDFs before they are printed.
46+
47+
One of **-w** or **-r** is required. **--copy** makes the mask reproduce the dots the printer already prints, rather than a pattern meant to hide them.
48+
49+
# CAVEATS
50+
51+
**-w** always writes **testpage.pdf**, and **-r** always writes **mask.json**, both in the current directory. Existing files at those names are overwritten.
52+
53+
The scan has to show the calibration dots. Margin scaling, a lossy format, or a driver that drops the yellow channel produces a mask that will not line up. **--copy** is a different operation from anonymisation: the printed page still carries a readable pattern.
54+
55+
# HISTORY
56+
57+
**deda_anonmask_create** is part of **DEDA**, written by **Timo Richter** and **Stephan Escher** and described in their **2018** paper on forensic analysis and anonymisation of printed documents.
58+
59+
# SEE ALSO
60+
61+
[deda_anonmask_apply](/man/deda_anonmask_apply)(1), [deda_parse_print](/man/deda_parse_print)(1), [deda_create_dots](/man/deda_create_dots)(1), [deda_clean_document](/man/deda_clean_document)(1)
62+
63+
# RESOURCES
64+
65+
```[Source code](https://github.com/dfd-tud/deda)```
66+
67+
<!-- verified: 2026-10-06 -->
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# TAGLINE
2+
3+
Remove yellow tracking dots from white areas of a scan
4+
5+
# TLDR
6+
7+
**Clean** a scan and write a new image
8+
9+
```deda_clean_document [scan.png] [cleaned.png]```
10+
11+
Also convert the result to **greyscale**
12+
13+
```deda_clean_document --secure [scan.png] [cleaned.png]```
14+
15+
# SYNOPSIS
16+
17+
**deda_clean_document** [_options_] _input_ _output_
18+
19+
# PARAMETERS
20+
21+
_input_
22+
23+
> Scan to read.
24+
25+
_output_
26+
27+
> File to write. The extension selects the output format.
28+
29+
**-s**, **--secure**
30+
31+
> Convert the cleaned image to greyscale.
32+
33+
**-g**, **--grayscale**
34+
35+
> Same as **--secure**.
36+
37+
# DESCRIPTION
38+
39+
**deda_clean_document** tries to remove yellow tracking dots from the white areas of a scanned page and writes the result to _output_. **--secure** (and its alias **--grayscale**) converts that result to greyscale, which drops the colour channel the dots are printed in.
40+
41+
This operates on a scan. It does not change a PDF that is about to be printed. Covering dots on a new printout is the job of **deda_anonmask_create** and **deda_anonmask_apply**.
42+
43+
# CAVEATS
44+
45+
Dots that sit on top of a photograph or other non-white ink are outside what this command removes. Greyscale mode discards colour from the whole page, not only the dots.
46+
47+
The command overwrites _output_ when that path already exists. It does not ask for confirmation.
48+
49+
# HISTORY
50+
51+
**deda_clean_document** is part of **DEDA**, written by **Timo Richter** and **Stephan Escher** and described in their **2018** paper on forensic analysis and anonymisation of printed documents.
52+
53+
# SEE ALSO
54+
55+
[deda_parse_print](/man/deda_parse_print)(1), [deda_anonmask_create](/man/deda_anonmask_create)(1), [deda_anonmask_apply](/man/deda_anonmask_apply)(1)
56+
57+
# RESOURCES
58+
59+
```[Source code](https://github.com/dfd-tud/deda)```
60+
61+
<!-- verified: 2026-10-06 -->
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# TAGLINE
2+
3+
Compare tracking dots across scanned pages
4+
5+
# TLDR
6+
7+
**Compare** two scans
8+
9+
```deda_compare_prints [page-a.png] [page-b.png]```
10+
11+
Compare **every scan** in a set
12+
13+
```deda_compare_prints [page1.png] [page2.png] [page3.png]```
14+
15+
Set the scan **resolution**
16+
17+
```deda_compare_prints -d [300] [page-a.png] [page-b.png]```
18+
19+
# SYNOPSIS
20+
21+
**deda_compare_prints** [_options_] _file_...
22+
23+
# PARAMETERS
24+
25+
_file_...
26+
27+
> One or more scans. At least one path is required.
28+
29+
**-d** _dpi_, **--dpi** _dpi_
30+
31+
> Resolution of the scans. **0**, the default, asks the reader to detect it.
32+
33+
**-v**, **--verbose**
34+
35+
> Repeat to print more diagnostic detail.
36+
37+
# DESCRIPTION
38+
39+
**deda_compare_prints** reads the tracking-dot pattern on each scan and groups the files by the printer it detected. When every file resolves to the same printer, it prints **IDENTICAL**. Otherwise it prints how many printers it found, a manufacturer label for each group, and the paths in that group. Files it could not read are listed under **Errors**.
40+
41+
The scans should be lossless and about **300** dpi, the same kind of input **deda_parse_print** expects.
42+
43+
# CAVEATS
44+
45+
A page with no detectable dots, or a pattern this toolkit does not know, shows up as an error or as its own group. That is not evidence that the printers differ. Pass **-d** when the image file does not store its resolution.
46+
47+
# HISTORY
48+
49+
**deda_compare_prints** is part of **DEDA**, written by **Timo Richter** and **Stephan Escher** and described in their **2018** paper on forensic analysis and anonymisation of printed documents.
50+
51+
# SEE ALSO
52+
53+
[deda_parse_print](/man/deda_parse_print)(1), [deda_extract_yd](/man/deda_extract_yd)(1), [deda_clean_document](/man/deda_clean_document)(1)
54+
55+
# RESOURCES
56+
57+
```[Source code](https://github.com/dfd-tud/deda)```
58+
59+
<!-- verified: 2026-10-06 -->
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# TAGLINE
2+
3+
Stamp a synthetic tracking-dot pattern onto a PDF
4+
5+
# TLDR
6+
7+
**Add** a dot pattern to a PDF
8+
9+
```deda_create_dots [page.pdf]```
10+
11+
Set the **serial** and **manufacturer** encoded in the dots
12+
13+
```deda_create_dots --serial [123456] --manufacturer [Epson] [page.pdf]```
14+
15+
Set the **timestamp** stored in the pattern
16+
17+
```deda_create_dots --year [18] --month [11] --day [11] --hour [11] --minutes [11] [page.pdf]```
18+
19+
Print the dots in **magenta** so they are easy to see
20+
21+
```deda_create_dots --debug [page.pdf]```
22+
23+
# SYNOPSIS
24+
25+
**deda_create_dots** [_options_] _pdf_
26+
27+
# PARAMETERS
28+
29+
_pdf_
30+
31+
> PDF the dots are added to. The original file is not modified.
32+
33+
**--serial** _n_
34+
35+
> Serial number encoded in the pattern. The default is **123456**.
36+
37+
**--manufacturer** _name_
38+
39+
> Manufacturer name encoded in the pattern. The default is **Epson**. The names this pattern accepts are **Xerox**, **Epson**, and **Dell**.
40+
41+
**--year** _n_, **--month** _n_, **--day** _n_, **--hour** _n_, **--minutes** _n_
42+
43+
> Timestamp fields encoded in the pattern. The defaults are year **18**, month **11**, day **11**, hour **11**, and minutes **11**.
44+
45+
**--dotradius** _inches_
46+
47+
> Radius of each dot, in inches. The default is the toolkit's built-in radius.
48+
49+
**--debug**
50+
51+
> Draw magenta dots instead of yellow ones.
52+
53+
# DESCRIPTION
54+
55+
**deda_create_dots** builds a tracking-dot matrix from the serial, manufacturer, and timestamp fields and stamps it onto a copy of a PDF. It prints the matrix, then writes **new_dots.pdf** in the working directory. The input PDF is left unchanged.
56+
57+
**--debug** uses magenta so the added dots are visible without a microscope. The calibration page from **deda_anonmask_create -w** can be used as the input PDF.
58+
59+
# CAVEATS
60+
61+
The output path is always **new_dots.pdf** in the current directory. A file of that name is overwritten. There is no flag to choose another path.
62+
63+
The manufacturer string has to be one the pattern tables include. An unknown name fails when the matrix is built. The year field is a two-digit value, matching the default of **18**.
64+
65+
# HISTORY
66+
67+
**deda_create_dots** is part of **DEDA**, written by **Timo Richter** and **Stephan Escher** and described in their **2018** paper on forensic analysis and anonymisation of printed documents.
68+
69+
# SEE ALSO
70+
71+
[deda_anonmask_create](/man/deda_anonmask_create)(1), [deda_anonmask_apply](/man/deda_anonmask_apply)(1), [deda_parse_print](/man/deda_parse_print)(1)
72+
73+
# RESOURCES
74+
75+
```[Source code](https://github.com/dfd-tud/deda)```
76+
77+
<!-- verified: 2026-10-06 -->

0 commit comments

Comments
 (0)