From a036de318edb06dec44dc9163298dbd7ddce7882 Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Thu, 30 Jul 2015 04:06:31 -0700 Subject: [PATCH] Replace mupdf and poppler with qpdf Drop two dependencies and replace them with one that does the job of both. Smells like progress. mupdf does PDF file repair and rendering poppler does rendering and page splitting qpdf does PDF file repair and page splitting ghostscript does PDF file repair, rendering, and page splitting (sort of) So we use qpdf. Ghostscript's page splitting is supposed is less efficient because it reprints the page (PDF -> Postscript -> PDF) and possibly loses quality. qpdf's library could be used to improve performance. This causes a slight performance regression: py.test tests/test_main.py::test_maximum_options went from 187 seconds up to 192. This is likely due to O(n) serialized invocations of qpdf compared to a single serialized call to pdfseparate. Could improve on this situation by using the example code in qpdf: pdf-split-pages.cc or create marker files in split_pages() and then write a new @transform function that would split pages on each CPU. Probably not worth it, overall, unless this causes problems on files with hundreds of pages. --- RELEASE_NOTES.rst | 4 +++- ocrmypdf/main.py | 26 +++++++++++++++----------- setup.py | 16 ++++------------ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 7a53c3de..bdfcaff3 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -41,12 +41,14 @@ Changes - GNU parallel_ - ImageMagick_ - Python 2.7 + - Poppler + - MuPDF_ tools - shell scripts - Some new external dependencies are required: - - MuPDF_ tools - Ghostscript 9.14+ + - qpdf 5.0.0+ - Unpaper_ 6.1 (optional) - some automatically managed Python dependencies diff --git a/ocrmypdf/main.py b/ocrmypdf/main.py index b2574123..97b9c0da 100755 --- a/ocrmypdf/main.py +++ b/ocrmypdf/main.py @@ -17,7 +17,7 @@ import PyPDF2 as pypdf from PIL import Image from subprocess import Popen, check_call, PIPE, CalledProcessError, \ - TimeoutExpired + TimeoutExpired, check_output try: from subprocess import DEVNULL except ImportError: @@ -319,11 +319,10 @@ def repair_pdf( log, pdfinfo, pdfinfo_lock): - args_mutool = [ - 'mutool', 'clean', - input_file, output_file + args_qpdf = [ + 'qpdf', input_file, output_file ] - check_call(args_mutool) + check_call(args_qpdf) with pdfinfo_lock: pdfinfo.extend(pdf_get_all_pageinfo(output_file)) @@ -388,12 +387,17 @@ def split_pages( for oo in output_files: with suppress(FileNotFoundError): os.unlink(oo) - args_pdfseparate = [ - 'pdfseparate', - input_file, - os.path.join(work_folder, '%06d.page.pdf') - ] - check_call(args_pdfseparate) + + pages = check_output(['qpdf', '--show-npages', input_file], + universal_newlines=True, close_fds=True) + + for n in range(int(pages)): + args_qpdf = [ + 'qpdf', input_file, + '--pages', input_file, '{0}'.format(n + 1), '--', + os.path.join(work_folder, '{0:06d}.page.pdf'.format(n + 1)) + ] + check_call(args_qpdf) from glob import glob for filename in glob(os.path.join(work_folder, '*.page.pdf')): diff --git a/setup.py b/setup.py index 4dff3f9d..ba3833f5 100644 --- a/setup.py +++ b/setup.py @@ -150,13 +150,6 @@ if command.startswith('install') or \ package='unpaper', optional=True ) - # Deprecated - check_external_program( - program='pdfseparate', - need_version='0.29.0', - package='poppler', - version_check_args=['-v'] - ) check_external_program( program='java', need_version='1.5.0', @@ -164,11 +157,10 @@ if command.startswith('install') or \ version_check_args=['-version'] ) check_external_program( - program='mutool', - need_version='1.7', - version_check_args=['-v'], - version_scrape_regex=re.compile(r'(\d+\.\d+[a-z]*)'), - package='mupdf-tools' + program='qpdf', + need_version='5.0.0', + package='qpdf', + version_check_args=['--version'] ) setup(