formula_img2latex/tests/conftest.py

68 lines
3.1 KiB
Python
Raw Normal View History

"""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