Refactor TextboxInfo

This commit is contained in:
James R. Barlow
2018-10-29 14:46:40 -07:00
parent d71fd089cb
commit 93623b2226
2 changed files with 22 additions and 38 deletions
+18 -13
View File
@@ -28,7 +28,7 @@ import xml.etree.ElementTree as ET
from pikepdf import PdfMatrix
import pikepdf
from .layout import get_textblocks, filter_textboxes, textbox_predicate
from .layout import get_page_analysis, get_text_boxes
from ..exec import ghostscript
from ..helpers import fspath
@@ -108,6 +108,9 @@ InlineSettings = namedtuple('InlineSettings',
ContentsInfo = namedtuple('ContentsInfo',
['xobject_settings', 'inline_images', 'found_text', 'found_vector'])
TextBoxInfo = namedtuple('TextBoxInfo',
['bbox', 'is_visible', 'is_corrupt'])
class VectorInfo:
def __init__(self):
@@ -590,15 +593,17 @@ def _page_has_text(text_blocks, page_width, page_height):
def simplify_textboxes(miner):
for box in filter_textboxes(miner, lambda x: True):
result = {}
"""Extract only limited content from text boxes
We do this to save memory and ensure that our objects are pickleable.
"""
for box in get_text_boxes(miner):
first_line = box._objs[0]
first_char = first_line._objs[0]
result['is_visible'] = (first_char.rendermode != 3)
result['is_corrupt'] = (first_char.get_text() == '\ufffd')
result['bbox'] = box.bbox
yield result
visible = (first_char.rendermode != 3)
corrupt = (first_char.get_text() == '\ufffd')
yield TextBoxInfo(box.bbox, visible, corrupt)
def _pdf_get_pageinfo(pdf, pageno: int, infile, xmltext):
@@ -612,14 +617,14 @@ def _pdf_get_pageinfo(pdf, pageno: int, infile, xmltext):
# fspath(infile), pageno, xmltext=xmltext)
with Path(infile).open('rb') as f:
miner = get_textblocks(f, pageno)
pageinfo['textobjs'] = list(simplify_textboxes(miner))
miner = get_page_analysis(f, pageno)
pageinfo['textboxes'] = list(simplify_textboxes(miner))
mediabox = [Decimal(d) for d in page.MediaBox.as_list()]
width_pt = mediabox[2] - mediabox[0]
height_pt = mediabox[3] - mediabox[1]
bboxes = (obj['bbox'] for obj in pageinfo['textobjs'])
bboxes = (box.bbox for box in pageinfo['textboxes'])
pageinfo['has_text'] = _page_has_text(
bboxes, width_pt, height_pt
)
@@ -748,14 +753,14 @@ class PageInfo:
def predicate(obj, want_visible, want_corrupt):
result = True
if want_visible is not None:
if obj['is_visible'] != want_visible:
if obj.is_visible != want_visible:
result = False
if want_corrupt is not None:
if obj['is_corrupt'] != want_corrupt:
if obj.is_corrupt != want_corrupt:
result = False
return result
return (obj['bbox'] for obj in self._pageinfo['textobjs']
return (obj.bbox for obj in self._pageinfo['textboxes']
if predicate(obj, visible, corrupt))
@property
+4 -25
View File
@@ -133,7 +133,7 @@ class TextPositionTracker(PDFLayoutAnalyzer):
return self.result
def get_textblocks(infile, pageno):
def get_page_analysis(infile, pageno):
rman = pdfminer.pdfinterp.PDFResourceManager(caching=True)
dev = TextPositionTracker(rman, laparams=LAParams())
interp = pdfminer.pdfinterp.PDFPageInterpreter(rman, dev)
@@ -148,33 +148,12 @@ def get_textblocks(infile, pageno):
return dev.get_result()
def textbox_predicate(*, visible, corrupt):
def real_predicate(textbox, want_visible=visible, want_corrupt=corrupt):
textline = textbox._objs[0]
first_char = textline._objs[0]
result = True
is_visible = (first_char.rendermode != 3)
if want_visible is not None:
if is_visible != want_visible:
result = False
is_corrupt = (first_char.get_text() == '\ufffd')
if want_corrupt is not None:
if is_corrupt != want_corrupt:
result = False
return result
return real_predicate
def filter_textboxes(obj, predicate):
def get_text_boxes(obj):
for child in obj:
if isinstance(child, (LTTextBox)):
if predicate(child):
yield child
yield child
else:
try:
yield from filter_textboxes(child, predicate)
yield from get_text_boxes(child)
except TypeError:
continue