Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
177349cc84 | ||
|
|
070c9772ce | ||
|
|
1bc09045a5 | ||
|
|
e46a18dd2f | ||
|
|
c64871c2ed |
@@ -28,6 +28,12 @@ tagged yet.
|
|||||||
|
|
||||||
.. |OCRmyPDF PyPI| image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
.. |OCRmyPDF PyPI| image:: https://img.shields.io/pypi/v/ocrmypdf.svg
|
||||||
|
|
||||||
|
v14.2.1
|
||||||
|
=======
|
||||||
|
|
||||||
|
- Fixed :issue:`977`, where images inside Form XObjects were always excluded
|
||||||
|
from image optimization.
|
||||||
|
|
||||||
v14.2.0
|
v14.2.0
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|||||||
+2
-6
@@ -37,16 +37,12 @@ classifiers = [
|
|||||||
"Intended Audience :: Science/Research",
|
"Intended Audience :: Science/Research",
|
||||||
"Intended Audience :: System Administrators",
|
"Intended Audience :: System Administrators",
|
||||||
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
|
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
|
||||||
"Operating System :: MacOS :: MacOS X",
|
"Operating System :: MacOS",
|
||||||
"Operating System :: Microsoft :: Windows :: Windows 10",
|
"Operating System :: Microsoft :: Windows",
|
||||||
"Operating System :: POSIX",
|
"Operating System :: POSIX",
|
||||||
"Operating System :: POSIX :: BSD",
|
"Operating System :: POSIX :: BSD",
|
||||||
"Operating System :: POSIX :: Linux",
|
"Operating System :: POSIX :: Linux",
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
|
||||||
"Programming Language :: Python :: 3.8",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Topic :: Scientific/Engineering :: Image Recognition",
|
"Topic :: Scientific/Engineering :: Image Recognition",
|
||||||
"Topic :: Text Processing :: Indexing",
|
"Topic :: Text Processing :: Indexing",
|
||||||
"Topic :: Text Processing :: Linguistic",
|
"Topic :: Text Processing :: Linguistic",
|
||||||
|
|||||||
+60
-23
@@ -230,6 +230,65 @@ def extract_image_generic(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _find_image_xrefs_container(
|
||||||
|
pdf: Pdf,
|
||||||
|
container: Object,
|
||||||
|
pageno: int,
|
||||||
|
include_xrefs: MutableSet[Xref],
|
||||||
|
exclude_xrefs: MutableSet[Xref],
|
||||||
|
pageno_for_xref: dict[Xref, int],
|
||||||
|
depth: int = 0,
|
||||||
|
):
|
||||||
|
"""Find all image XRefs in a page or Form XObject and add to the include/exclude sets."""
|
||||||
|
if depth > 10:
|
||||||
|
log.warning("Recursion depth exceeded in _find_image_xrefs_page")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
xobjs = container.Resources.XObject
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
for _imname, image in dict(xobjs).items():
|
||||||
|
if image.objgen[1] != 0:
|
||||||
|
continue # Ignore images in an incremental PDF
|
||||||
|
if Name.Subtype in image and image.Subtype == Name.Form:
|
||||||
|
# Recurse into Form XObjects
|
||||||
|
log.debug(f"Recursing into Form XObject {_imname} in page {pageno}")
|
||||||
|
_find_image_xrefs_container(
|
||||||
|
pdf,
|
||||||
|
image,
|
||||||
|
pageno,
|
||||||
|
include_xrefs,
|
||||||
|
exclude_xrefs,
|
||||||
|
pageno_for_xref,
|
||||||
|
depth + 1,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
xref = Xref(image.objgen[0])
|
||||||
|
if Name.SMask in image:
|
||||||
|
# Ignore soft masks
|
||||||
|
smask_xref = Xref(image.SMask.objgen[0])
|
||||||
|
exclude_xrefs.add(smask_xref)
|
||||||
|
log.debug(f"xref {smask_xref}: skipping image because it is an SMask")
|
||||||
|
include_xrefs.add(xref)
|
||||||
|
log.debug(f"xref {xref}: treating as an optimization candidate")
|
||||||
|
if xref not in pageno_for_xref:
|
||||||
|
pageno_for_xref[xref] = pageno
|
||||||
|
|
||||||
|
|
||||||
|
def _find_image_xrefs(pdf: Pdf):
|
||||||
|
include_xrefs: MutableSet[Xref] = set()
|
||||||
|
exclude_xrefs: MutableSet[Xref] = set()
|
||||||
|
pageno_for_xref: dict[Xref, int] = {}
|
||||||
|
|
||||||
|
for pageno, page in enumerate(pdf.pages):
|
||||||
|
_find_image_xrefs_container(
|
||||||
|
pdf, page, pageno, include_xrefs, exclude_xrefs, pageno_for_xref
|
||||||
|
)
|
||||||
|
|
||||||
|
working_xrefs = include_xrefs - exclude_xrefs
|
||||||
|
return working_xrefs, pageno_for_xref
|
||||||
|
|
||||||
|
|
||||||
def extract_images(
|
def extract_images(
|
||||||
pike: Pdf,
|
pike: Pdf,
|
||||||
root: Path,
|
root: Path,
|
||||||
@@ -250,30 +309,8 @@ def extract_images(
|
|||||||
it does a tuple should be returned: (xref, ext) where .ext is the file
|
it does a tuple should be returned: (xref, ext) where .ext is the file
|
||||||
extension. extract_fn must also extract the file it finds interesting.
|
extension. extract_fn must also extract the file it finds interesting.
|
||||||
"""
|
"""
|
||||||
include_xrefs: MutableSet[Xref] = set()
|
|
||||||
exclude_xrefs: MutableSet[Xref] = set()
|
|
||||||
pageno_for_xref = {}
|
|
||||||
errors = 0
|
errors = 0
|
||||||
for pageno, page in enumerate(pike.pages):
|
working_xrefs, pageno_for_xref = _find_image_xrefs(pike)
|
||||||
try:
|
|
||||||
xobjs = page.Resources.XObject
|
|
||||||
except AttributeError:
|
|
||||||
continue
|
|
||||||
for _imname, image in dict(xobjs).items():
|
|
||||||
if image.objgen[1] != 0:
|
|
||||||
continue # Ignore images in an incremental PDF
|
|
||||||
xref = Xref(image.objgen[0])
|
|
||||||
if Name.SMask in image:
|
|
||||||
# Ignore soft masks
|
|
||||||
smask_xref = Xref(image.SMask.objgen[0])
|
|
||||||
exclude_xrefs.add(smask_xref)
|
|
||||||
log.debug(f"xref {smask_xref}: skipping image because it is an SMask")
|
|
||||||
include_xrefs.add(xref)
|
|
||||||
log.debug(f"xref {xref}: treating as an optimization candidate")
|
|
||||||
if xref not in pageno_for_xref:
|
|
||||||
pageno_for_xref[xref] = pageno
|
|
||||||
|
|
||||||
working_xrefs = include_xrefs - exclude_xrefs
|
|
||||||
for xref in working_xrefs:
|
for xref in working_xrefs:
|
||||||
image = pike.get_object((xref, 0))
|
image = pike.get_object((xref, 0))
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -204,3 +204,11 @@ def test_group3(resources, outdir):
|
|||||||
assert (
|
assert (
|
||||||
opt.extract_image_filter(pdf, outdir, im, im.objgen[0]) is None
|
opt.extract_image_filter(pdf, outdir, im, im.objgen[0]) is None
|
||||||
), "Group 3 should be disallowed"
|
), "Group 3 should be disallowed"
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_formx(resources, outdir):
|
||||||
|
with pikepdf.open(resources / 'formxobject.pdf') as pdf:
|
||||||
|
working, pagenos = opt._find_image_xrefs(pdf)
|
||||||
|
assert len(working) == 1
|
||||||
|
xref = next(iter(working))
|
||||||
|
assert pagenos[xref] == 0
|
||||||
|
|||||||
Reference in New Issue
Block a user