# PDF tooling — extended reference

Supplement to `SKILL.md`: extra libraries, CLI tools, and patterns for tasks beyond the bundled scripts.

## Python: pypdfium2 (PDFium bindings)

Useful for fast rasterization and text extraction without a full layout engine.

```python
import pypdfium2 as pdfium
from PIL import Image

doc = pdfium.PdfDocument("input.pdf")
page = doc[0]
bitmap = page.render(scale=2.0)
img = bitmap.to_pil()
img.save("page1.png")
```

Iterate `range(len(doc))` for all pages. Tune `scale` for DPI needs.

## JavaScript: pdf-lib

Create or rewrite PDFs in Node or the browser: load bytes, copy pages between documents, draw vector text and shapes, save bytes.

```javascript
const { PDFDocument, StandardFonts, rgb } = require("pdf-lib");
const fs = require("fs");

(async () => {
  const bytes = fs.readFileSync("in.pdf");
  const pdf = await PDFDocument.load(bytes);
  const font = await pdf.embedFont(StandardFonts.Helvetica);
  const page = pdf.getPages()[0];
  page.drawText("Hello", { x: 72, y: 720, size: 12, font, color: rgb(0, 0, 0) });
  fs.writeFileSync("out.pdf", await pdf.save());
})();
```

Merge/split by copying selected page indices between `PDFDocument` instances.

## JavaScript: pdfjs-dist (PDF.js)

Render in `<canvas>`, walk `getTextContent()` for tokens, or read annotations via `page.getAnnotations()`. Remember to point `GlobalWorkerOptions.workerSrc` at the matching `pdf.worker` build when bundling.

## Poppler CLI (`pdftotext`, `pdftoppm`, `pdfimages`)

- `pdftotext -bbox-layout doc.pdf out.xml` — text with layout boxes (XML).
- `pdftoppm -png -r 200 doc.pdf prefix` — page images.
- `pdfimages -list doc.pdf` — embedded image inventory.

## qpdf

Linearize for web, extract page ranges, or merge selected pages from several files (`qpdf --empty --pages ...`). Good for repair/normalization pipelines.

## Tables from PDFs

**Bundled:** `extract_tables_from_pdf.py` uses pdfplumber's built-in `extract_tables()` — handles most ruled and semi-ruled vector tables. For edge cases (complex merged cells, borderless tables), consider:

- **Camelot** / **Tabula** — more configurable table detection; Camelot needs Ghostscript, Tabula needs Java.

## OCR

**Bundled:** `ocr_pdf.py` uses pytesseract + pdf2image for end-to-end OCR of scanned pages (outputs Markdown). Requires Tesseract binary on PATH.

For advanced use cases (custom PSM modes, HOCR output, cloud OCR), pipe rasterized images through **Tesseract** CLI directly or use a cloud OCR API.

## Image extraction

**Bundled:** `extract_images_from_pdf.py` uses pypdf's `page.images` API to extract embedded images as PNG.

For lower-level control or listing embedded image metadata, use Poppler CLI: `pdfimages -list doc.pdf`.

---

When in doubt, prefer the **bundled Python scripts** for tasks already wrapped there (`md_export_from_pdf.py`, `burst_pdf_pages.py`, etc.) so behavior stays consistent with automation tests.
