test: end-to-end gray image-mask OCR across rasterizers (#1688)

This commit is contained in:
James R. Barlow
2026-06-05 11:40:50 -07:00
parent 91b6a818f5
commit 0db130e1c3
+61
View File
@@ -242,6 +242,67 @@ class TestRasterizerHookDirect:
assert im.mode == '1'
def _make_text_mask_pdf(path, fill: bytes):
"""Build a letter page with a large text image mask painted with ``fill``.
The mask is a 1-bit stencil; ``fill`` is the color operator sequence that
sets the paint color (e.g. ``b"0.263 0.263 0.263 rg"``). With a gray fill
this reproduces issue #1688: the text is mid-gray, which is dithered into
noise if rasterized to 1-bit but reads correctly once promoted to gray.
"""
from PIL import ImageDraw, ImageFont
w, h = 1700, 600
im = Image.new('1', (w, h), 1) # 1 = white = "do not paint" under Decode [0 1]
draw = ImageDraw.Draw(im)
try:
font = ImageFont.truetype("DejaVuSans-Bold.ttf", 220)
except OSError:
font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 220
)
draw.text((40, 120), "TESTING", fill=0, font=font)
packed = im.tobytes() # 1-bpc, rows byte-padded, MSB first
pdf = pikepdf.Pdf.new()
pdf.add_blank_page(page_size=(612, 792))
mask = pikepdf.Stream(pdf, packed)
mask.Type = pikepdf.Name.XObject
mask.Subtype = pikepdf.Name.Image
mask.Width = w
mask.Height = h
mask.ImageMask = True
mask.BitsPerComponent = 1
name = pdf.pages[0].add_resource(mask, pikepdf.Name.XObject)
pdf.pages[0].Contents = pikepdf.Stream(
pdf, b"q 560 0 0 200 26 500 cm %s %s Do Q" % (fill, bytes(name))
)
pdf.save(path)
return path
@pytest.mark.parametrize("rasterizer", ['ghostscript', 'pypdfium'])
def test_gray_mask_ocrs_to_text(tmp_path, rasterizer):
"""A gray-painted text mask OCRs to real text on both rasterizers (#1688)."""
if rasterizer == 'pypdfium' and not PYPDFIUM_AVAILABLE:
pytest.skip("pypdfium2 not installed")
src = _make_text_mask_pdf(tmp_path / 'mask.pdf', b"0.263 0.263 0.263 rg")
out = tmp_path / 'out.pdf'
sidecar = tmp_path / 'out.txt'
check_ocrmypdf(
src,
out,
'--rasterizer',
rasterizer,
'--sidecar',
str(sidecar),
'--oversample',
'300',
)
assert 'TESTING' in sidecar.read_text().upper()
def _create_gradient_image(width: int, height: int) -> Image.Image:
"""Create an image with multiple gradients to detect rasterization errors.