Detect and warn about Tagged PDFs
This commit is contained in:
@@ -33,6 +33,7 @@ from ocrmypdf.exceptions import (
|
||||
EncryptedPdfError,
|
||||
InputFileError,
|
||||
PriorOcrFoundError,
|
||||
TaggedPDFError,
|
||||
UnsupportedImageFormatError,
|
||||
)
|
||||
from ocrmypdf.helpers import IMG2PDF_KWARGS, Resolution, safe_symlink
|
||||
@@ -218,6 +219,16 @@ def validate_pdfinfo_options(context: PdfContext) -> None:
|
||||
"form and all filled form fields. The output PDF will be "
|
||||
"'flattened' and will no longer be fillable."
|
||||
)
|
||||
if pdfinfo.is_tagged:
|
||||
if options.force_ocr or options.skip_text or options.redo_ocr:
|
||||
log.warning(
|
||||
"This PDF is marked as a Tagged PDF. This often indicates "
|
||||
"that the PDF was generated from an office document and does "
|
||||
"not need OCR. PDF pages processed by OCRmyPDF may not be "
|
||||
"tagged correctly."
|
||||
)
|
||||
else:
|
||||
raise TaggedPDFError()
|
||||
context.plugin_manager.hook.validate(pdfinfo=pdfinfo, options=options)
|
||||
|
||||
|
||||
|
||||
@@ -108,10 +108,16 @@ class EncryptedPdfError(ExitCodeException):
|
||||
)
|
||||
|
||||
|
||||
class DigitalSignatureError(ExitCodeException):
|
||||
class TesseractConfigError(ExitCodeException):
|
||||
"""Tesseract config can't be parsed."""
|
||||
|
||||
exit_code = ExitCode.invalid_config
|
||||
message = "Error occurred while parsing a Tesseract configuration file"
|
||||
|
||||
|
||||
class DigitalSignatureError(InputFileError):
|
||||
"""PDF has a digital signature."""
|
||||
|
||||
exit_code = ExitCode.input_file
|
||||
message = dedent(
|
||||
"""\
|
||||
Input PDF has a digital signature. OCR would alter the document,
|
||||
@@ -120,8 +126,14 @@ class DigitalSignatureError(ExitCodeException):
|
||||
)
|
||||
|
||||
|
||||
class TesseractConfigError(ExitCodeException):
|
||||
"""Tesseract config can't be parsed."""
|
||||
class TaggedPDFError(InputFileError):
|
||||
"""PDF is tagged."""
|
||||
|
||||
exit_code = ExitCode.invalid_config
|
||||
message = "Error occurred while parsing a Tesseract configuration file"
|
||||
message = dedent(
|
||||
"""\
|
||||
This PDF is marked as a Tagged PDF. This often indicates
|
||||
that the PDF was generated from an office document and does
|
||||
not need OCR. Use --force-ocr, --skip-text or --redo-ocr to
|
||||
override this error.
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -1038,7 +1038,11 @@ DEFAULT_EXECUTOR = SerialExecutor()
|
||||
|
||||
|
||||
class PdfInfo:
|
||||
"""Get summary information about a PDF."""
|
||||
"""Extract summary information about a PDF without retaining the PDF itself.
|
||||
|
||||
Crucially this lets us get the information in a pure Python format so that
|
||||
it can be pickled and passed to a worker process.
|
||||
"""
|
||||
|
||||
_has_acroform: bool = False
|
||||
_has_signature: bool = False
|
||||
@@ -1078,6 +1082,9 @@ class PdfInfo:
|
||||
elif Name.XFA in pdf.Root.AcroForm:
|
||||
self._has_acroform = True
|
||||
self._has_signature = bool(pdf.Root.AcroForm.get(Name.SigFlags, 0) & 1)
|
||||
self._is_tagged = bool(
|
||||
pdf.Root.get(Name.MarkInfo, {}).get(Name.Marked, False)
|
||||
)
|
||||
|
||||
@property
|
||||
def pages(self) -> Sequence[PageInfo | None]:
|
||||
@@ -1105,6 +1112,11 @@ class PdfInfo:
|
||||
"""Return True if the document annotations has a digital signature."""
|
||||
return self._has_signature
|
||||
|
||||
@property
|
||||
def is_tagged(self) -> bool:
|
||||
"""Return True if the document catalog indicates this is a Tagged PDF."""
|
||||
return self._is_tagged
|
||||
|
||||
@property
|
||||
def filename(self) -> str | Path:
|
||||
"""Return filename of PDF."""
|
||||
|
||||
Reference in New Issue
Block a user