Improve PDF/A validity checking at end

This commit is contained in:
James R. Barlow
2016-08-03 01:26:16 -07:00
parent 0746083301
commit 12575d594a
3 changed files with 56 additions and 13 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ class ExitCode(IntEnum):
bad_args = 1
input_file = 2
missing_dependency = 3
invalid_output_pdfa = 4
invalid_output_pdf = 4
file_access_error = 5
already_done_ocr = 6
child_process_error = 7
+18 -12
View File
@@ -27,7 +27,7 @@ import ruffus.proxy_logger as proxy_logger
from .hocrtransform import HocrTransform
from .pageinfo import pdf_get_all_pageinfo
from .pdfa import generate_pdfa_def
from .pdfa import generate_pdfa_def, file_claims_pdfa
from . import ghostscript
from . import tesseract
from . import qpdf
@@ -127,8 +127,12 @@ parser.add_argument(
'--image-dpi', metavar='DPI', type=int,
help="for input image instead of PDF, use this DPI instead of file's")
parser.add_argument(
'--output-type', choices=['pdfa', 'pdf'], default='pdf',
help="choose output type")
'--output-type', choices=['pdfa', 'pdf'], default='pdfa',
help="Choose output type. 'pdfa' creates a PDF/A-2b compliant file for "
"long term archiving (default, recommended) but may not suitable "
"for users who want their file altered as little as possible. 'pdfa' "
"also has problems with full Unicode text. 'pdf' attempts to "
"preserve file contents as much as possible.")
metadata = parser.add_argument_group(
"Metadata options",
@@ -1220,12 +1224,6 @@ def copy_final(
shutil.copy(input_file, output_file)
def validate_pdfa(
input_file,
log):
return qpdf.check(input_file, log)
def available_cpu_count():
try:
return multiprocessing.cpu_count()
@@ -1360,9 +1358,17 @@ def run_pipeline():
_log.error(e)
return ExitCode.other_error
if not validate_pdfa(options.output_file, _log):
_log.warning('Output file: The generated PDF/A file is INVALID')
return ExitCode.invalid_output_pdfa
if options.output_type == 'pdfa':
pdfa_info = file_claims_pdfa(options.output_file)
if pdfa_info['pass']:
_log.info(pdfa_info['message'])
else:
_log.warning(pdfa_info['message'])
return ExitCode.invalid_output_pdf
if not qpdf.check(options.output_file, _log):
_log.warning('Output file: The generated PDF is INVALID')
return ExitCode.invalid_output_pdf
with _pdfinfo_lock:
_log.debug(_pdfinfo)
+37
View File
@@ -7,6 +7,7 @@ from __future__ import print_function, absolute_import, division
from string import Template
import codecs
import pkg_resources
import PyPDF2 as pypdf
ICC_PROFILE_RELPATH = 'data/sRGB.icc'
@@ -108,3 +109,39 @@ def generate_pdfa_def(target_filename, pdfmark, icc='sRGB'):
# answer), insist on ascii
with open(target_filename, 'w', encoding='ascii') as f:
f.write(ps)
def file_claims_pdfa(filename):
"""Determines if the file claims to be PDF/A compliant
Checking if a file is a truly compliant PDF/A is a massive undertaking
that no open source tool does properly. Some commercial tools are
generally reliable (Acrobat).
This checks if the XMP metadata contains a PDF/A marker.
"""
pdf = pypdf.PdfFileReader(filename)
xmp = pdf.getXmpMetadata()
pdfa_nodes = xmp.getNodesInNamespace(
aboutUri='',
namespace='http://www.aiim.org/pdfa/ns/id/')
pdfa_dict = {attr.localName: attr.value for attr in pdfa_nodes}
pdfa_dict['pass'] = False
if pdfa_dict:
part_conformance = pdfa_dict['part'] + pdfa_dict['conformance']
valid_part_conforms = {'1A', '1B', '2A', '2B', '2U', '3A', '3B', '3U'}
message = 'File claims to be PDF/A-{}'.format(
part_conformance)
if part_conformance in valid_part_conforms:
pdfa_dict['pass'] = True
pdfa_dict['message'] = message
else:
pdfa_dict['message'] = 'File is a regular PDF'
return pdfa_dict