Skip to content

Commit 4f93187

Browse files
committed
Add screenshot annotation support and update related documentation
- Introduced `annotate.sh` script to render annotated screenshots into build/images/ - Added `annotations/README.md` to explain the annotation process and types - Updated `README.md` to include details about screenshot annotations - Modified `install.sh` to include dependencies for annotation rendering - Enhanced `build.sh` and `build-web.sh` to utilize annotated images if available - Updated `.gitignore` to exclude build artifacts and added new annotation files - Created example annotation file `status.yaml` for reference
1 parent 8aace74 commit 4f93187

11 files changed

Lines changed: 419 additions & 14 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# Generated web edition (staged docs + built static site)
88
/web/
99

10+
# Annotated screenshots baked from images/ + annotations/ at build time
11+
/build/
12+
1013
# Reference source material (fetched on demand, not distributed here)
1114
tools/v9manual.pdf
1215
tools/v9manual.txt

CLAUDE.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ done:**
3232
- an image referenced by a chapter (`images/`)
3333
- build configuration: `metadata.yaml`, `tools/reference.docx`, `tools/build.sh`,
3434
`mkdocs.yml`, `tools/build-web.sh`
35+
- a screenshot annotation under `annotations/` (see *Annotating screenshots* below)
3536

3637
`generate.sh` / `generate-web.sh` do **not** require a running FPP. A missing
3738
screenshot is a non-fatal warning (Pandoc substitutes the image's caption text;
@@ -50,6 +51,31 @@ Word styling automatically — there is no separate PDF stylesheet to maintain.
5051
LibreOffice isn't installed the PDF step is skipped with a hint and the `.docx`
5152
still builds; run `PDF=0 ./generate.sh` to skip the PDF deliberately.
5253

54+
## Annotating screenshots (arrows, callouts, redactions)
55+
56+
Screenshots can be marked up **declaratively** so `capture.sh` can still re-shoot
57+
the raw images: `images/` stays pristine and annotations are baked on at build time
58+
into `build/images/`, which every deliverable then uses. When the maintainer asks to
59+
annotate an image (e.g. "put an arrow on the Save button and number the tabs on
60+
`status.png`"):
61+
62+
1. **Read the source image** (`images/<name>.png`) to find pixel coordinates —
63+
the Read tool shows it to you; coordinates are pixels from the top-left.
64+
2. **Write/edit the sidecar** `annotations/<name>.yaml` (same stem as the image).
65+
Supported types: `box`, `circle`, `marker` (numbered badge), `arrow`,
66+
`highlight`, `text`, `blur` (redaction). Full format + an example are in
67+
`annotations/README.md`.
68+
3. **Preview and verify placement**: run `./annotate.sh`, then Read
69+
`build/images/<name>.png` and adjust coordinates until it looks right. Iterate
70+
here rather than rebuilding the whole manual each time.
71+
4. **Rebuild the deliverables** (`./generate.sh` and `./generate-web.sh`) — both
72+
apply annotations automatically.
73+
74+
Rendering is `tools/annotate.py` (Pillow + PyYAML). If those libs are missing the
75+
build falls back to un-annotated images with a warning, so the manual still builds;
76+
`./install.sh` installs them (`python3-pil`, `python3-yaml`). `annotations/` is the
77+
source of truth (committed); `build/` is a git-ignored artifact.
78+
5379
## Conventions
5480

5581
- Chapters are combined in **filename order**; the numeric prefixes (`00-`, `02-`,

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ from a running FPP web UI, and rendered to `.docx` with Pandoc.
1414
install.sh Install the build/capture dependencies (Debian/Ubuntu)
1515
generate.sh Build FPP_Manual_v10.docx (+ .pdf) from the chapters (no FPP needed)
1616
generate-web.sh Build the browsable web edition into web/site/ (no FPP needed)
17+
annotate.sh Render annotated screenshots into build/images/ for preview
1718
capture.sh (Re)capture screenshots from a running FPP web UI
1819
metadata.yaml Title-page metadata for the document
1920
mkdocs.yml MkDocs config for the web edition (theme, nav, search)
2021
OUTLINE.md Chapter plan / structure
2122
chapters/ The manual, one Markdown file per chapter (combined in
2223
filename order, e.g. 00-*, 02-*, 20-* ...)
23-
images/ Screenshots referenced by the chapters
24+
images/ Raw screenshots referenced by the chapters (kept pristine)
25+
annotations/ Optional YAML sidecars that mark up screenshots (see README there)
2426
tools/
2527
build.sh Pandoc build (invoked by generate.sh)
2628
build-web.sh MkDocs build (invoked by generate-web.sh)
29+
annotate.py Bakes annotations/ onto images/ at build time (Pillow)
2730
shoot.py Headless-Chromium screenshot driver (Chrome DevTools
2831
Protocol; Python standard library only)
2932
shotlist.txt The list of pages to screenshot
@@ -78,6 +81,29 @@ Enable it once under **repo Settings → Pages → Build and deployment → Sour
7881
"GitHub Actions"**; the site then goes live at the `site_url` in `mkdocs.yml`
7982
(<https://falconchristmas.github.io/fpp-manual-generator/>).
8083

84+
## Annotating screenshots
85+
86+
Screenshots can be marked up with arrows, boxes, numbered callouts, highlights,
87+
text labels, and blur/redactions — **without touching the raw images**. The raw
88+
captures in `images/` stay pristine (so `capture.sh` can re-shoot them); the markup
89+
lives in small YAML sidecars under `annotations/` and is baked on at build time into
90+
`build/images/`, which the `.docx`, `.pdf`, and web builds all use automatically.
91+
92+
```bash
93+
# 1. describe the overlays for images/status.png in annotations/status.yaml
94+
# 2. preview placement:
95+
./annotate.sh # renders build/images/*.png (images/ untouched)
96+
# 3. rebuild the deliverables (they apply annotations for you):
97+
./generate.sh
98+
./generate-web.sh
99+
```
100+
101+
Coordinates are pixels from the top-left of the source screenshot. The full sidecar
102+
format, the list of annotation types, and an example are in
103+
[`annotations/README.md`](annotations/README.md). Rendering needs `python3-pil` and
104+
`python3-yaml` (installed by `./install.sh`); if they're missing the build falls
105+
back to un-annotated images with a warning, so the manual still builds.
106+
81107
## Requirements
82108

83109
- **pandoc** – Markdown → `.docx`.
@@ -86,8 +112,10 @@ Enable it once under **repo Settings → Pages → Build and deployment → Sour
86112
and skips the PDF (or run `PDF=0 ./generate.sh` to skip it deliberately).
87113
- **mkdocs-material** – builds the web edition (`./generate-web.sh`). Only needed
88114
for the web output; the `.docx`/`.pdf` build doesn't use it.
115+
- **python3-pil** / **python3-yaml** – render the screenshot annotations. Only
116+
needed if `annotations/` is used; the build degrades to raw images without them.
89117
- **chromium** – headless screenshots. Started detached by `shoot.py`.
90-
- **python3** – build/capture scripts (standard library only; no `pip` needed).
118+
- **python3** – build/capture scripts.
91119
- **poppler-utils** – only used when refreshing content from a reference PDF.
92120
- A **running FPP** reachable over HTTP is required for `capture.sh` (not for
93121
`generate.sh`).

annotate.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
# Render annotated screenshots into build/images/ for preview.
3+
#
4+
# Annotations live in annotations/<image-stem>.yaml and are drawn onto the raw
5+
# screenshots from images/. This standalone run is handy for checking placement
6+
# (render, then open build/images/<name>.png) — but you don't have to run it by
7+
# hand: generate.sh and generate-web.sh apply annotations automatically.
8+
#
9+
# Needs python3-pil + python3-yaml (see ./install.sh).
10+
set -e
11+
HERE="$(cd "$(dirname "$0")" && pwd)"
12+
python3 "$HERE/tools/annotate.py" "$HERE/images" "$HERE/annotations" "$HERE/build/images"
13+
echo "Annotated images in build/images/ (raw screenshots in images/ are untouched)."

annotations/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Screenshot annotations
2+
3+
Declarative overlays (arrows, boxes, numbered callouts, highlights, redactions)
4+
for the manual's screenshots. The raw screenshots in `../images/` stay pristine so
5+
`../capture.sh` can always re-shoot them; annotations are baked on at build time
6+
into `build/images/` and flow into the `.docx`, `.pdf`, and web outputs.
7+
8+
## How it works
9+
10+
- One YAML sidecar per image, named after the image: `status.yaml` annotates
11+
`../images/status.png`. Files without a sidecar are used unchanged.
12+
- Coordinates are **pixels from the top-left** of the source image. Open the
13+
screenshot to read them off (in Claude Code, the Read tool shows the image).
14+
- Preview with `../annotate.sh` (writes `../build/images/`), then rebuild with
15+
`../generate.sh` and/or `../generate-web.sh`. Both apply annotations
16+
automatically — `annotate.sh` is only for checking placement.
17+
18+
## Annotation types
19+
20+
| type | keys | draws |
21+
|-------------|--------------------------------------------------|-------|
22+
| `box` | `at: [x1,y1,x2,y2]`, optional `label` | rectangle outline (+ numbered badge at the corner if `label`) |
23+
| `circle` | `at: [cx,cy]`, `radius`, optional `label` | circle outline (+ badge at centre if `label`) |
24+
| `marker` | `at: [x,y]`, `label` | filled numbered callout badge |
25+
| `arrow` | `from: [x,y]`, `to: [x,y]` | arrow (head at `to`) |
26+
| `highlight` | `at: [x1,y1,x2,y2]` | translucent filled rectangle |
27+
| `text` | `at: [x,y]`, `text: "…"` | text with a white halo for legibility |
28+
| `blur` | `at: [x1,y1,x2,y2]`, optional `radius` | Gaussian-blur redaction of the region |
29+
30+
Shared optional keys on any annotation: `color` (name like `red`, `#rrggbb`, or
31+
`[r,g,b]`; default red) and `width` (stroke thickness in px; default auto-scales to
32+
the image size).
33+
34+
## Example
35+
36+
`status.yaml` (annotating `../images/status.png`):
37+
38+
```yaml
39+
annotations:
40+
- {type: box, at: [40, 70, 420, 130], color: red, label: "1"}
41+
- {type: arrow, from: [600, 300], to: [470, 150], color: red}
42+
- {type: marker, at: [820, 96], label: "2"}
43+
- {type: blur, at: [1150, 20, 1420, 60]} # hide the hostname/IP
44+
```

annotations/status.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Annotations for images/status.png (1440 x 1071).
2+
#
3+
# This is a WORKED STARTER you can copy for other images. The active annotations
4+
# below number the six elements of the header bar, matching the numbered list in
5+
# chapters/20-status-page.md ("The header bar"). Coordinates are pixels from the
6+
# top-left; read the screenshot to find them (in Claude Code, the Read tool shows
7+
# the image). Preview with ./annotate.sh, then look at build/images/status.png.
8+
#
9+
# Every annotation type is shown as a commented reference at the bottom.
10+
11+
annotations:
12+
# Numbered callouts sitting just below each header-bar element (left -> right),
13+
# so the elements themselves stay visible.
14+
- {type: marker, at: [135, 72], label: "1"} # FPP logo + version
15+
- {type: marker, at: [993, 72], label: "2"} # host name
16+
- {type: marker, at: [1063, 72], label: "3"} # player state
17+
- {type: marker, at: [1122, 72], label: "4"} # sensors (CPU temp)
18+
- {type: marker, at: [1240, 72], label: "5"} # IP addresses
19+
- {type: marker, at: [1322, 72], label: "6"} # time
20+
21+
# --- Reference: the other annotation types (uncomment / adapt as needed) -----
22+
# - {type: box, at: [x1, y1, x2, y2], color: red, label: "A"} # outline (+badge)
23+
# - {type: circle, at: [cx, cy], radius: 40, color: "#1e88e5"} # ring
24+
# - {type: arrow, from: [x1, y1], to: [x2, y2], color: red} # pointer
25+
# - {type: highlight, at: [x1, y1, x2, y2], color: yellow} # translucent fill
26+
# - {type: text, at: [x, y], text: "Label", color: red} # haloed caption
27+
# - {type: blur, at: [x1, y1, x2, y2]} # redact (hide IP etc.)
28+
#
29+
# Shared optional keys on any annotation: color (name / #rrggbb / [r,g,b]) and
30+
# width (stroke px). See annotations/README.md for the full reference.

chapters/20-status-page.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@ is running in, **Player** or **Remote**, the screen looks a little different.
1212

1313
## The header bar
1414

15-
The header appears on every page and gives at‑a‑glance status: the FPP **logo**
16-
and **version** (the version links to the *System Upgrade* page), the **host
17-
name**, the current **player state**, **sensors** (such as CPU temperature), the
18-
device's **IP addresses**, and the **time**. *Press F1 for help* opens
19-
context‑sensitive help for the current page.
15+
The header appears on every page and gives at‑a‑glance status. The numbered
16+
callouts above correspond to:
17+
18+
1. **Logo and version** – the FPP logo with the version number beside it; the
19+
version links to the *System Upgrade* page.
20+
2. **Host name** – the device's configured host name.
21+
3. **Player state** – whether FPP is idle or playing.
22+
4. **Sensors** – readings such as CPU temperature.
23+
5. **IP addresses** – the device's active network addresses.
24+
6. **Time** – the device's current date and time.
25+
26+
*Press F1 for help* (top right) opens context‑sensitive help for the current page.
2027

2128
## Player Status Page
2229

install.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
# chromium - headless browser used to screenshot the FPP web UI
1010
# poppler-utils - pdftotext/pdfinfo, used only when refreshing content from a
1111
# reference PDF (optional; safe to keep)
12-
# python3 - runs the build and screenshot scripts (standard library only)
12+
# python3 - runs the build and screenshot scripts
13+
# python3-pil - Pillow: draws screenshot annotations (annotations/ -> images)
14+
# python3-yaml - reads the annotation sidecar files
1315
#
1416
# Works on the FPP OS image (Debian) and other Debian/Ubuntu systems.
1517
set -e
@@ -20,14 +22,15 @@ if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi
2022
echo "Updating package lists..."
2123
$SUDO apt-get update
2224

23-
echo "Installing pandoc, poppler-utils, python3, chromium, libreoffice-writer, mkdocs-material..."
25+
echo "Installing pandoc, poppler-utils, python3, python3-pil, python3-yaml, chromium, libreoffice-writer, mkdocs-material..."
2426
# libreoffice-writer (not the full suite) is enough for the headless docx->pdf
2527
# conversion and is much smaller.
2628
# mkdocs-material builds the web edition; it pulls in mkdocs itself as a dep.
29+
# python3-pil (Pillow) + python3-yaml render the screenshot annotations.
2730
# The Chromium package is named 'chromium' on Debian and 'chromium-browser' on
2831
# some Ubuntu releases; try both.
29-
$SUDO apt-get install -y pandoc poppler-utils python3 libreoffice-writer mkdocs-material chromium \
30-
|| $SUDO apt-get install -y pandoc poppler-utils python3 libreoffice-writer mkdocs-material chromium-browser
32+
$SUDO apt-get install -y pandoc poppler-utils python3 python3-pil python3-yaml libreoffice-writer mkdocs-material chromium \
33+
|| $SUDO apt-get install -y pandoc poppler-utils python3 python3-pil python3-yaml libreoffice-writer mkdocs-material chromium-browser
3134

3235
echo
3336
echo "Install complete."

0 commit comments

Comments
 (0)