miscs (Interro02) : horizontal cutting resolution

This commit is contained in:
2026-09-14 22:20:46 +02:00
parent 5080274e8f
commit 0a86403ca6
28 changed files with 1447 additions and 59 deletions
+92
View File
@@ -0,0 +1,92 @@
"""Compare extracted answers against the same Poppler view used for labels."""
import tempfile
import unittest
from pathlib import Path
import numpy as np
import pymupdf
from pdf2image import convert_from_path
from copienator.commands.splitting_int import _render_split_outputs
class SplittingGeometryTests(unittest.TestCase):
def make_source(self, path, rotation, cropped=True):
with pymupdf.open() as document:
page = document.new_page(width=800, height=1000)
# Asymmetric colours exercise both translation and orientation.
for row in range(20):
for column in range(8):
colour = (row / 20, column / 8, (row + column) % 7 / 7)
page.draw_rect(
pymupdf.Rect(column * 100, row * 50,
(column + 1) * 100, (row + 1) * 50),
color=None, fill=colour,
)
page.insert_text((200, 500), "Middle of the answer")
if cropped:
page.set_cropbox(pymupdf.Rect(20, 80, 760, 920))
page.set_rotation(rotation)
document.save(path)
def assert_matches_preview(self, answer, preview, bounds):
actual = np.asarray(convert_from_path(answer, dpi=72)[0]).astype(float)
expected = np.asarray(preview.crop(bounds)).astype(float)
self.assertEqual(actual.shape, expected.shape)
self.assertLess(np.abs(actual - expected).mean(), 0.5)
def test_cropped_and_uncropped_pages_at_every_rotation(self):
visible = {
0: (20, 80, 760, 920),
90: (80, 20, 920, 760),
180: (40, 80, 780, 920),
270: (80, 40, 920, 780),
}
for rotation in (0, 90, 180, 270):
for cropped in (False, True):
for full_answer in (False, True):
with self.subTest(rotation=rotation, cropped=cropped, full=full_answer):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
source = root / "copy.pdf"
self.make_source(source, rotation, cropped)
before = source.read_bytes()
preview = convert_from_path(source, dpi=72, use_cropbox=False)[0]
width, height = preview.size
bounds = visible[rotation] if cropped else (0, 0, width, height)
if full_answer:
coordinates = [("A", 0, 0, 10, 0, 100)]
else:
coordinates = [("A", 0, 250, 260, 0, 100),
("_", 0, 711, 721, 0, 100)]
bounds = (bounds[0], max(bounds[1], height // 4),
bounds[2], min(bounds[3], height * 3 // 4))
_render_split_outputs(source, coordinates, root)
self.assert_matches_preview(root / "A.pdf", preview, bounds)
self.assertEqual(source.read_bytes(), before)
def test_answer_continues_to_bottom_then_next_page(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
source = root / "copy.pdf"
first = root / "first.pdf"
second = root / "second.pdf"
self.make_source(first, 180)
self.make_source(second, 0)
with pymupdf.open() as document:
for path in (first, second):
with pymupdf.open(path) as part:
document.insert_pdf(part)
document.save(source)
previews = convert_from_path(source, dpi=72, use_cropbox=False)
_render_split_outputs(source, [("A", 0, 700, 720, 0, 100),
("_", 1, 211, 230, 500, 600)], root)
rendered = convert_from_path(root / "A.pdf", dpi=72)
self.assertEqual(len(rendered), 2)
for actual, preview, bounds in zip(rendered, previews,
[(40, 700, 780, 920), (20, 80, 760, 250)]):
expected = np.asarray(preview.crop(bounds)).astype(float)
actual = np.asarray(actual).astype(float)
self.assertEqual(actual.shape, expected.shape)
self.assertLess(np.abs(actual - expected).mean(), 0.5)