"""Shared fixtures: synthetic formula images and a minimal epub2md output directory.""" from __future__ import annotations import io import json import shutil from pathlib import Path import cv2 import numpy as np import pytest from PIL import Image from formula_img2latex.render import render_many needs_latex = pytest.mark.skipif(shutil.which("pdflatex") is None, reason="pdflatex fehlt") needs_pandoc = pytest.mark.skipif(shutil.which("pandoc") is None, reason="pandoc fehlt") def synth_image(tex: str, display: bool = False, px_per_pt: float = 1.41, fmt: str = "JPEG", offset: tuple[int, int] = (1, 2), preset: str = "cm") -> bytes: """Render *tex* like a small e-book formula image (Gehrke-like: ~1.4 px/pt, JPEG).""" r = render_many([(tex, display)], preset)[0] assert r.ok, r.error gray = 1.0 - r.rasterize(px_per_pt * 4) pad = np.ones((gray.shape[0] + 8, gray.shape[1] + 8), np.float32) oy, ox = offset pad[oy:oy + gray.shape[0], ox:ox + gray.shape[1]] = gray h, w = pad.shape[0] // 4, pad.shape[1] // 4 small = cv2.resize(pad[: h * 4, : w * 4], (w, h), interpolation=cv2.INTER_AREA) buf = io.BytesIO() im = Image.fromarray((small * 255).astype(np.uint8)) if fmt == "PNG-ALPHA": # black ink on transparent background (Springer style) rgba = Image.new("RGBA", im.size, (0, 0, 0, 0)) rgba.putalpha(Image.fromarray(255 - np.asarray(im))) rgba.save(buf, "PNG") else: im.save(buf, fmt, **({"quality": 75} if fmt == "JPEG" else {})) return buf.getvalue() @pytest.fixture def epub2md_dir(tmp_path: Path) -> Path: """Minimal epub2md output with two formula images (one inline, one display) and a figure.""" root = tmp_path / "buch" (root / "chapters").mkdir(parents=True) (root / "media" / "images").mkdir(parents=True) imgs = { "0001-inline.jpg": synth_image(r"L=\{-\sqrt{2};\sqrt{2}\}", px_per_pt=2.2), "0002-display.jpg": synth_image(r"x_{2,k}=\arcsin\left(-\frac{3}{5}\right)+2k\pi", display=True, px_per_pt=2.2), } for name, data in imgs.items(): (root / "media" / "images" / name).write_bytes(data) color = np.zeros((40, 60, 3), np.uint8) color[:, :, 2] = 200 Image.fromarray(color).save(root / "media" / "images" / "0003-figure.png") (root / "chapters" / "001-kapitel.md").write_text( "---\nchapter_title: Test\n---\n\n# Kapitel\n\n" "Die Lösungsmenge lautet ![x](../media/images/0001-inline.jpg).\n\n" "Allgemein gilt\n\n![y](../media/images/0002-display.jpg)\n\n" "```\n![kein](../media/images/0001-inline.jpg)\n```\n\n" "![Abbildung](../media/images/0003-figure.png)\n", encoding="utf-8") report = {"tool": "epub2md", "options": {"math": "auto"}, "input": {"name": "buch.epub", "sha256": "x"}, "media": {"files": [{"source": f"OEBPS/{n}", "file": f"media/images/{n}"} for n in imgs]}, "warnings": [{"code": "formula-image", "message": "Formel liegt nur als Bild vor (0002-display.jpg)."}]} (root / "conversion-report.json").write_text(json.dumps(report), encoding="utf-8") return root