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:
James R. Barlow
2017-03-29 23:43:26 -07:00
parent 4a9e9e9db2
commit 1e7fbd4202
3 changed files with 85 additions and 9 deletions
+21 -2
View File
@@ -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:
+3 -2
View File
@@ -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
View File
@@ -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']