mcpbeat Sign in

Photo To Scanned PDF Skill for Claude

>- Two pipelines ending at a scanner-look PDF. (1) Phone photos of paper documents (contracts, stamped certificates, receipts, forms, handwritten 做成扫描件", "photos to scanned PDF", "make this look scanned", "手机拍的 文档转 PDF", "盖章文件扫描", replacing pages in an existing scanned PDF, any CamScanner-like request. (2) A digital document with no signature yet (rendered docx/PDF, confirmation form, contract draft) → make it look it onto the signature line, apply the same scan-look post-processing. "synthesize a signature", any request for a document that needs to look signed without a real photographed signature. Do NOT hand-roll levels/contrast enhancement for scan-look — tried and rejected twice; this skill's pipeline is the proven one.

14k tokens
context cost
the whole folder, loaded on every use
7
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
1314
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/daymade/claude-code-skills --skill photo-to-scanned-pdf

The instruction itself

9 sections, as written by the author

Photo → Scanned PDF

Two related pipelines, same destination look, different starting point:

phone photos of paper documents, or a digital document that needs a synthetic

signature before it looks signed. The pipelines that work, and the failure

modes that ship wrong PDFs if skipped.

Which one do you need?

| The input is... | Use |

|---|---|

| Phone photos of an already-signed/stamped paper document | This file, main pipeline below |

| A digital document (docx/PDF) with no signature yet, and you need to make it look hand-signed | references/digital-signature-synthesis.md |

photos ──► rectify (photo_to_scan.py --raw)
       ──► ORDER BY CONTENT, detect colored paper   ← agent eyes, not filenames
       ──► enhance: noteshrink (white batch with -g │ colored pages separately,
                                after white-balance pre-pass)
       ──► assemble_pdf.py → A4 PDF
       ──► make_contact_sheet.py → READ IT, verify EVERY page   ← mandatory

Division of labor: scripts carry execution; you (the agent) carry the two

judgment steps — content-based page ordering, and whole-document verification.

Neither can be automated away: filenames lie about order, and per-page spot

checks miss wrong-slot bugs. The digital-signature branch shares this same

philosophy with its own two judgment calls — see the reference file.

Step 0 — Dependencies

which pdftoppm || brew install poppler   # contact sheet + any PDF rendering
uvx noteshrink --help | head -3          # first run builds it (~30 s)

Scripts are uv run single-file scripts (PEP 723); OpenCV/PIL/img2pdf resolve

automatically on first run.

Step 1 — Rectify

uv run <skill>/scripts/photo_to_scan.py --raw --out-dir work --prefix page \
    photo1.jpg photo2.jpg ...

Expected: one page_NN.jpg per photo, each tagged [quad]. A

[FULLFRAME-fallback] tag means the paper outline wasn't found (busy background,

page cut off) — view that photo and decide: retake, or accept the uncropped frame.

The script handles EXIF rotation internally (cv2.imread ignores EXIF; phone

photos come rotated — this silently produces sideways pages if you rectify with

raw OpenCV).

Step 2 — Order by content, detect colored paper (agent judgment)

Read every rectified image (batch of ~6 per message) and record two things:

  • Its identity — date, title, page number, whatever distinguishes pages.

Batch-exported photos (WeChat, AirDrop) get timestamps of the *export*

moment, often all within one second — filename order is meaningless. Real

case: 17 photos turned out to be in exact reverse document order; only

content reading caught it.

  • Its paper color — white, or colored (blue/yellow/pink stock)? Colored

pages take a different path in Step 3. If unsure, sample programmatically:

mean RGB of a blank region; B > R + 25 ⇒ blue-ish paper.

Build the final page order as an explicit list before proceeding. If pages are

supposed to match an external register (an invoice list, a session table),

cross-check identity against it now — missing/duplicate pages found here cost

seconds; found after delivery they cost a redo.

Step 3 — Enhance (noteshrink, split by paper color)

White-paper pages — one batch, global palette:

uvx noteshrink -w -g -K -q -b ns -c "true" page_03.jpg page_01.jpg page_07.jpg ...
# inputs IN FINAL PAGE ORDER → outputs ns0000.png, ns0001.png, ... in that order
  • -w white background, -g one global palette (uniform ink/stamp color across

pages), -K keep given order, -c "true" skips its internal PDF step (we

assemble ourselves).

  • Pass filenames explicitly. zsh does not word-split $VAR — a file list in

a variable arrives as one giant "filename", noteshrink exits without output,

and -q keeps it silent. Verify outputs exist (ls ns0*.png) rather than

trusting stdout.

Colored-paper pages — separate, with white-balance pre-pass:

uv run <skill>/scripts/photo_to_scan.py --out-dir work --prefix wb colored_photo.jpg   # no --raw
uvx noteshrink -w -g -K -q -b nc -c "true" work/wb_01.jpg

Two distinct failure modes force this split (both shipped as bugs before the

rule existed):

  • Colored pages inside the -g batch poison the whole document — the paper

color enters the global palette and white pages come out with tinted

shadows/artifacts.

  • **noteshrink alone on colored paper whitens the background but not the

foreground cast** — black ink photographed on blue stock reads blue-purple, a

red stamp reads maroon. The default (non---raw) mode of photo_to_scan.py

divides out the paper color first, so ink returns to black and stamps to red.

Step 4 — Assemble

uv run <skill>/scripts/assemble_pdf.py --out scanned.pdf \
    ns0000.png ns0001.png nc0000.png ns0002.png ...   # FINAL page order

Expected: OK scanned.pdf (N pages, ~0.05 MB/page). Edge crop (default

24px top / 12px sides at 200 dpi) removes the sliver of desk surface that

rectification drags in along page borders; document margins dwarf it.

Step 5 — Verify the WHOLE document (mandatory, not optional)

uv run <skill>/scripts/make_contact_sheet.py scanned.pdf --out contact.png

Read contact.png and check every page: identity sequence complete and

correct (each date/title where it should be, no duplicates, none missing), no

off-color page, stamps/signatures present. Then spot-read 1–2 pages at full

resolution for text sharpness.

Why whole-document, every time: two shipped-bug stories from the session this

skill was distilled from —

  • A page-replacement task wrote the new page into the wrong slot (an

off-by-one in a copy command), silently overwriting a neighboring page. The

per-page check of the replaced slots passed; the clobbered neighbor was only

caught by the user.

  • A palette-poisoning bug (Step 3 #1) tinted pages that were *not* being

edited. Checking only the edited pages missed it.

The cost asymmetry is absolute: contact sheet = one Read; a wrong page in a

delivered PDF = redo + lost trust. **"I verified the pages I changed" is not

verification.**

Replacing pages in an existing scanned PDF

Keep the per-page enhanced PNGs (ns*/nc*) as the working set. To replace page

k: process the new photo through Steps 1–3, overwrite that page's PNG, re-run

Steps 4–5. When copying into numbered slots, mind the mapping — slot numbers

shift when photo order was reversed; derive the slot from the page's *content

identity*, never from its position in the photo batch. Then the Step 5 full

check is what actually protects you.

Troubleshooting

| Symptom | Cause / fix |

|---|---|

| Output "doesn't look scanned" — gray haze, soft text | You hand-rolled levels/curves/divide enhancement. Don't — two attempts were rejected by a real user before switching to noteshrink (background sampling + palette quantization is what produces the flat-white scan look). |

| White pages have tinted shadows | A colored-paper page was inside the -g batch. Re-run whites-only batch (Step 3). |

| Ink looks blue/purple, stamp looks maroon on a colored page | noteshrink got the colored page raw. Insert the white-balance pre-pass (photo_to_scan.py without --raw). |

| noteshrink produced no output, no error | File list passed via an unquoted shell variable under zsh (no word splitting), or paths with spaces. Pass explicit filenames; check ls ns0*.png. |

| Page sideways / upside down | EXIF ignored somewhere upstream, or the quad landed landscape. photo_to_scan.py corrects EXIF + rotates to portrait; upside-down pages it cannot know — catch at Step 2 and rotate the source photo. |

| [FULLFRAME-fallback] on a photo | Paper outline not detected (low contrast vs table, page cut off). Retake against a dark background, or accept full frame + rely on edge crop. |

| Thin dark strip along page edge in the PDF | Desk surface dragged in by rectification. Raise --crop-top/--crop-side in assemble_pdf.py. |

| Pages in wrong order in the PDF | Filename-order assumption. Order comes from Step 2 content reading, passed explicitly to noteshrink (-K) and assemble_pdf.py. |

Other skills for the same job

different authors, same section of the catalogue
DOCX
by anthropics
vendor ×16

Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks

7k tokens
PDF
by anthropics
vendor ×16

Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.

13k tokens scripts
PPTX
by JayZeeDesign
×15

Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks

308k tokens scripts
Canvas Design
by anthropics
vendor ×13

Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.

1388k tokens
PDF
by anthropics
vendor ×10

Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.

15k tokens scripts
DOCX
by w95
×6

Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation.

5k tokens
PPTX
by w95
×4

Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill.

2k tokens
Obsidian Markdown
by ZhanlinCui
×3

Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.

3k tokens

How to use it

Copy the folder

Take daymade/photo-to-scanned-pdf from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference uvx, brew. Without those the skill loads but fails at the first command.