diff --git a/ocrmypdf/pdfinfo.py b/ocrmypdf/pdfinfo.py index 2621eb43..8d498769 100644 --- a/ocrmypdf/pdfinfo.py +++ b/ocrmypdf/pdfinfo.py @@ -693,6 +693,10 @@ class PdfInfo: # The minimum PDF is the maximum version that any particular page needs return max(page.min_version for page in self.pages) + @property + def has_userunit(self): + return any(page.userunit for page in self.pages) + def __getitem__(self, item): return self._pages[item] diff --git a/ocrmypdf/pipeline.py b/ocrmypdf/pipeline.py index caa4dc7a..f3dfe04c 100644 --- a/ocrmypdf/pipeline.py +++ b/ocrmypdf/pipeline.py @@ -184,9 +184,19 @@ def repair_pdf( output_file, log, context): - + options = context.get_options() qpdf.repair(input_file, output_file, log) pdfinfo = PdfInfo(output_file) + + if pdfinfo.has_userunit and options.output_type == 'pdfa': + log.error("This input file uses a PDF feature that is not supported " + "by Ghostscript, so you cannot use --output-type=pdfa for this " + "file. (Specifically, it uses the PDF-1.6 /UserUnit feature to " + "support very large or small page sizes, and Ghostscript cannot " + "output these files.) Use --output-type=pdf instead." + ) + raise InputFileError() + context.set_pdfinfo(pdfinfo) log.debug(pdfinfo) @@ -432,8 +442,8 @@ def rasterize_with_ghostscript( input_file, output_file, xres=dpi, yres=dpi, raster_device=device, log=log) else: - # Ghostscript respects /UserUnit when rasterizing so replace the - # image's DPI with the working DPI + # Ghostscript respects /UserUnit when rasterizing. Rasterize at + # the true DPI but rewrite the output image to the working DPI. ghostscript.rasterize_pdf( input_file, output_file + '.tmp', xres=true_dpi, yres=true_dpi, raster_device=device, log=log) @@ -499,7 +509,7 @@ def select_ocr_image( infiles, output_file, log, - contenxt): + context): """Select the image we send for OCR. May not be the same as the display image depending on preprocessing.""" diff --git a/tests/test_userunit.py b/tests/test_userunit.py new file mode 100644 index 00000000..b486873a --- /dev/null +++ b/tests/test_userunit.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# © 2017 James R. Barlow: github.com/jbarlow83 + +from subprocess import Popen, PIPE, check_output, check_call, DEVNULL +import os +import shutil +import pytest +from ocrmypdf.pdfinfo import PdfInfo, Colorspace, Encoding +import PyPDF2 as pypdf +from ocrmypdf.exceptions import ExitCode +from ocrmypdf import leptonica +from ocrmypdf.pdfa import file_claims_pdfa +from ocrmypdf.exec import ghostscript +import logging +from math import isclose + + +check_ocrmypdf = pytest.helpers.check_ocrmypdf +run_ocrmypdf = pytest.helpers.run_ocrmypdf +spoof = pytest.helpers.spoof + +@pytest.fixture +def spoof_tesseract_noop(): + return spoof(tesseract='tesseract_noop.py') + + +@pytest.fixture +def spoof_tesseract_cache(): + if pytest.helpers.running_in_docker(): + return os.environ.copy() + return spoof(tesseract="tesseract_cache.py") + + +@pytest.fixture +def poster(resources): + return resources / 'poster.pdf' + + +def test_userunit_ghostscript_fails(poster, no_outpdf): + p, out, err = run_ocrmypdf(poster, no_outpdf, '--output-type=pdfa') + assert p.returncode == ExitCode.input_file