Fix issues with —pdf-renderer tess4 page skipping
If tess4 renderer needed to skip OCR on a page it would end up duplicating the page contents onto the new page, rather than creating a blank OCR layer and placing it on the output page. This created duplicated content in output files.
This commit is contained in:
@@ -11,6 +11,7 @@ from ..helpers import page_number
|
||||
from . import get_program
|
||||
from collections import namedtuple
|
||||
from textwrap import dedent
|
||||
import PyPDF2 as pypdf
|
||||
|
||||
from subprocess import Popen, PIPE, CalledProcessError, \
|
||||
TimeoutExpired, check_output, STDOUT, DEVNULL
|
||||
@@ -272,6 +273,24 @@ def generate_hocr(input_file, output_hocr, language: list, engine_mode,
|
||||
f_out.write(line)
|
||||
|
||||
|
||||
def use_skip_page(text_only, skip_pdf, output_pdf):
|
||||
if not text_only:
|
||||
os.symlink(skip_pdf, output_pdf)
|
||||
return
|
||||
|
||||
# For text only we must create a blank page with dimensions identical
|
||||
# to the skip page because this is equivalent to a page with no text
|
||||
|
||||
pdf_in = pypdf.PdfFileReader(skip_pdf)
|
||||
page0 = pdf_in.pages[0]
|
||||
|
||||
with open(output_pdf, 'wb') as out:
|
||||
pdf_out = pypdf.PdfFileWriter()
|
||||
w, h = page0.mediaBox.getWidth(), page0.mediaBox.getHeight()
|
||||
pdf_out.addBlankPage(w, h)
|
||||
pdf_out.write(out)
|
||||
|
||||
|
||||
def generate_pdf(input_image, skip_pdf, output_pdf, language: list,
|
||||
engine_mode, text_only: bool,
|
||||
tessconfig: list, timeout: float, pagesegmode: int, log):
|
||||
@@ -309,14 +328,14 @@ def generate_pdf(input_image, skip_pdf, output_pdf, language: list,
|
||||
universal_newlines=True, timeout=timeout)
|
||||
except TimeoutExpired:
|
||||
page_timedout(log, input_image)
|
||||
shutil.copy(skip_pdf, output_pdf)
|
||||
use_skip_page(text_only, skip_pdf, output_pdf)
|
||||
except CalledProcessError as e:
|
||||
tesseract_log_output(log, e.output, input_image)
|
||||
if 'read_params_file: parameter not found' in e.output:
|
||||
raise TesseractConfigError() from e
|
||||
|
||||
if 'Image too large' in e.output:
|
||||
shutil.copy(skip_pdf, output_pdf)
|
||||
use_skip_page(text_only, skip_pdf, output_pdf)
|
||||
return
|
||||
raise e from e
|
||||
else:
|
||||
|
||||
@@ -773,7 +773,8 @@ def generate_postscript_stub(
|
||||
def skip_page(
|
||||
input_file,
|
||||
output_file,
|
||||
log):
|
||||
log,
|
||||
context):
|
||||
# The purpose of this step is its filter to forward only the skipped
|
||||
# files (.skip.oriented.pdf) while disregarding the processed ones
|
||||
# (.ocr.oriented.pdf). Alternative would be for merge_pages to filter
|
||||
@@ -1048,7 +1049,7 @@ def build_pipeline(options, work_folder, log, context):
|
||||
filter=suffix('.skip.oriented.pdf'),
|
||||
output='.done.pdf',
|
||||
output_dir=work_folder,
|
||||
extras=[log])
|
||||
extras=[log, context])
|
||||
|
||||
# Merge pages
|
||||
task_merge_pages_ghostscript = main_pipeline.merge(
|
||||
|
||||
+61
-5
@@ -6,11 +6,42 @@ from ocrmypdf.exceptions import ExitCode
|
||||
from ocrmypdf.exec import tesseract
|
||||
from ocrmypdf import pageinfo
|
||||
import sys
|
||||
import os
|
||||
import PyPDF2 as pypdf
|
||||
|
||||
|
||||
spoof = pytest.helpers.spoof
|
||||
|
||||
|
||||
def tess4_possible_location():
|
||||
"""The location of tesseract 4 may be OCRMYPDF_TESS4, OCRMYPDF_TESSERACT,
|
||||
or the installed version on PATH."""
|
||||
return os.environ.get('OCRMYPDF_TESS4') or \
|
||||
os.environ.get('OCRMYPDF_TESSERACT') or \
|
||||
'tesseract'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ensure_tess4():
|
||||
return spoof(tesseract=tess4_possible_location())
|
||||
|
||||
|
||||
def tess4_available():
|
||||
"""Check if a tesseract 4 binary is available, even if it's not the
|
||||
official "tesseract" on PATH
|
||||
|
||||
"""
|
||||
old_environ = os.environ.copy()
|
||||
try:
|
||||
os.environ['OCRMYPDF_TESSERACT'] = tess4_possible_location()
|
||||
return tesseract.v4() and tesseract.has_textonly_pdf()
|
||||
finally:
|
||||
os.environ = old_environ
|
||||
|
||||
|
||||
# Skip all tests in this file if not tesseract 4
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not (tesseract.v4() and tesseract.has_textonly_pdf()),
|
||||
not tess4_available(),
|
||||
reason="tesseract 4.0 with textonly_pdf feature required")
|
||||
|
||||
check_ocrmypdf = pytest.helpers.check_ocrmypdf
|
||||
@@ -18,14 +49,15 @@ run_ocrmypdf = pytest.helpers.run_ocrmypdf
|
||||
spoof = pytest.helpers.spoof
|
||||
|
||||
|
||||
def test_textonly_pdf(resources, outdir):
|
||||
def test_textonly_pdf(ensure_tess4, resources, outdir):
|
||||
check_ocrmypdf(
|
||||
resources / 'linn.pdf',
|
||||
outdir / 'linn_textonly.pdf', '--pdf-renderer', 'tess4')
|
||||
outdir / 'linn_textonly.pdf', '--pdf-renderer', 'tess4',
|
||||
env=ensure_tess4)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 5), reason="needs math.isclose")
|
||||
def test_pagesize_consistency_tess4(resources, outpdf):
|
||||
def test_pagesize_consistency_tess4(ensure_tess4, resources, outpdf):
|
||||
from math import isclose
|
||||
|
||||
infile = resources / 'linn.pdf'
|
||||
@@ -35,9 +67,33 @@ def test_pagesize_consistency_tess4(resources, outpdf):
|
||||
check_ocrmypdf(
|
||||
infile,
|
||||
outpdf, '--pdf-renderer', 'tess4',
|
||||
'--clean', '--deskew', '--remove-background', '--clean-final')
|
||||
'--clean', '--deskew', '--remove-background', '--clean-final',
|
||||
env=ensure_tess4)
|
||||
|
||||
after_dims = pytest.helpers.first_page_dimensions(outpdf)
|
||||
|
||||
assert isclose(before_dims[0], after_dims[0])
|
||||
assert isclose(before_dims[1], after_dims[1])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('basename', ['graph_ocred.pdf', 'cardinal.pdf'])
|
||||
def test_skip_pages_does_not_replicate(
|
||||
ensure_tess4, resources, basename, outdir):
|
||||
infile = resources / basename
|
||||
outpdf = outdir / basename
|
||||
|
||||
check_ocrmypdf(
|
||||
infile,
|
||||
outpdf, '--pdf-renderer', 'tess4', '--force-ocr',
|
||||
'--tesseract-timeout', '0',
|
||||
env=ensure_tess4
|
||||
)
|
||||
|
||||
info_in = pageinfo.pdf_get_all_pageinfo(str(infile))
|
||||
|
||||
info = pageinfo.pdf_get_all_pageinfo(str(outpdf))
|
||||
for page in info:
|
||||
assert len(page['images']) == 1, "skipped page was replicated"
|
||||
|
||||
for n in range(len(info_in)):
|
||||
assert info[n]['width_inches'] == info_in[n]['width_inches']
|
||||
|
||||
Reference in New Issue
Block a user